Added examples for advertisers.

Change-Id: If292c9bbc4dca61a2cd8f8dcf7e5532dd1f81206
diff --git a/Makefile b/Makefile
index ed28a23..a985e6d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,8 @@
-PWD := $(shell pwd)
-
 include ../shared/mojo.mk
 
 # ANDROID needs to be any positive integer (e.g., 1, 2, 3, 4...)
 ifdef ANDROID
-	BUILD_DIR := $(PWD)/gen/mojo/android
+	BUILD_DIR := $(CURDIR)/gen/mojo/android
 
 	# For some reason we need to set the origin flag when running on Android,
 	# but setting it on Linux causes errors.
@@ -16,12 +14,14 @@
 	DEVICE_ID := $(shell adb devices | sed -n $(ANDROID_PLUS_ONE)p | awk '{ print $$1; }')
 	DEVICE_FLAG := --target-device $(DEVICE_ID)
 	ANDROID_FLAG := --android
+	DISCOVERY_DIR := $(CURDIR)/../discovery/gen/mojo/android
 else
-	BUILD_DIR := $(PWD)/gen/mojo/linux_amd64
+	BUILD_DIR := $(CURDIR)/gen/mojo/linux_amd64
+	DISCOVERY_DIR := $(CURDIR)/../discovery/gen/mojo/linux_amd64
 endif
 
 # Add the discovery mojom output to the go path.
-export GOPATH := $(PWD)/../discovery/gen/go
+GOPATH := $(GOPATH):$(CURDIR)/../discovery/go
 
 # If this is not the first mojo shell, then you must reuse the devservers
 # to avoid a "port in use" error.
@@ -35,7 +35,7 @@
 
 # Build the v23proxy.mojo, client, and associated go examples.
 .PHONY: build-go
-build-go: $(BUILD_DIR)/v23proxy.mojo build-go-examples
+build-go: $(BUILD_DIR)/v23proxy.mojo $(BUILD_DIR)/discovery.mojo build-go-examples
 
 # Build the v23proxy client and its associated dart examples.
 .PHONY: build-dart
@@ -54,7 +54,7 @@
 upgrade-packages:
 	pub upgrade
 
-build-go-examples: $(BUILD_DIR)/echo_client.mojo $(BUILD_DIR)/echo_server.mojo $(BUILD_DIR)/fortune_client.mojo $(BUILD_DIR)/fortune_server.mojo
+build-go-examples: $(BUILD_DIR)/echo_client.mojo $(BUILD_DIR)/echo_server.mojo $(BUILD_DIR)/fortune_client.mojo $(BUILD_DIR)/fortune_server.mojo $(BUILD_DIR)/echo_client_discovery.mojo $(BUILD_DIR)/echo_server_discovery.mojo
 
 build-dart-examples: gen/echo.mojom.dart gen/fortune.mojom.dart
 
@@ -89,6 +89,13 @@
 $(BUILD_DIR)/echo_server.mojo: gen/go/src/mojom/examples/echo/echo.mojom.go
 	$(call MOGO_BUILD,examples/echo/server,$@)
 
+$(BUILD_DIR)/echo_client_discovery.mojo: gen/go/src/mojom/examples/echo/echo.mojom.go
+	$(call MOGO_BUILD,examples/advertiser/client,$@)
+
+$(BUILD_DIR)/echo_server_discovery.mojo: gen/go/src/mojom/examples/echo/echo.mojom.go
+	$(call MOGO_BUILD,examples/advertiser/server,$@)
+
+
 gen/go/src/mojom/examples/echo/echo.mojom.go: mojom/mojom/examples/echo.mojom | mojo-env-check
 	$(call MOJOM_GEN,$<,mojom,gen,go)
 	gofmt -w $@
@@ -102,6 +109,10 @@
 $(BUILD_DIR)/fortune_server.mojo: gen/go/src/mojom/examples/fortune/fortune.mojom.go
 	$(call MOGO_BUILD,examples/fortune/server,$@)
 
+$(BUILD_DIR)/discovery.mojo:
+	make -C ../discovery build
+	cp $(DISCOVERY_DIR)/discovery.mojo $(BUILD_DIR)/discovery.mojo
+
 gen/go/src/mojom/examples/fortune/fortune.mojom.go: mojom/mojom/examples/fortune.mojom | mojo-env-check
 	$(call MOJOM_GEN,$<,mojom,gen,go)
 	gofmt -w $@
@@ -137,7 +148,7 @@
 	rm -f lib/gen/mojom/$(notdir $@)
 
 gen-vdl:
-	GOPATH=$(PWD)/go VDLPATH=$(PWD)/go vdl generate all
+	GOPATH=$(CURDIR)/go VDLPATH=$(CURDIR)/go vdl generate all
 
 # Run the Mojo shell with map-origin. This is common to Linux and Android since
 # the latter cannot accept a config-file.
@@ -157,7 +168,7 @@
 	$(REUSE_FLAG) \
 	$(ORIGIN_FLAG) \
 	--map-origin="https://mojo.v.io/=$(BUILD_DIR)" \
-	--map-origin="https://mojodart.v.io/=$(PWD)" \
+	--map-origin="https://mojodart.v.io/=$(CURDIR)" \
 	--args-for="https://mojo$4.v.io/$2 $3" \
 	https://mojo$4.v.io/$2
 endef
@@ -176,6 +187,11 @@
 	$(call RUN_MOJO_SHELL,--enable-multiprocess,v23proxy.mojo,,)
 
 
+.PHONY: start-advertising-server
+start-advertising-server: build-go
+	$(call RUN_MOJO_SHELL,--enable-multiprocess,echo_server_discovery.mojo,,)
+
+
 # Start the echo client. This uses the v23proxy (client-side) to speak Vanadium
 # over to the v23proxy (server-side) [OR a 0-authentication Vanadium echo server].
 #
@@ -191,6 +207,21 @@
 start-echo-client: build-go
 	$(call RUN_MOJO_SHELL,,echo_client.mojo,${ARGS},)
 
+# Start the echo client that uses discovery. This uses the v23proxy (client-side) to speak Vanadium
+# over to the v23proxy (server-side) [OR a 0-authentication Vanadium echo server].
+#
+# On Linux, run with
+# HOME={tmpdir} make ARGS="[optional: a string to echo]" start-echo-discovery-client
+#
+# On Android, run with
+# ANDROID={device number} make ARGS="[optional: a string to echo]" start-echo-discovery-client
+#
+# Note1: Does not use --enable-multiprocess since small Go programs can omit it.
+# Note2: Setting HOME ensures that we avoid a db LOCK that is created per mojo shell instance.
+.PHONY: start-echo-discovery-client
+start-echo-discovery-client: build-go
+	$(call RUN_MOJO_SHELL,,echo_client.mojo,${ARGS},)
+
 # Like the start-echo-client but using a Dart client instead.
 # Note: Uses --enable-multiprocess since it looks like the Dart VM and Go VM
 # together are enough to cause a SIGSEGV (Android signal 11 crash) if this flag
diff --git a/go/src/examples/advertiser/client/scanner.go b/go/src/examples/advertiser/client/scanner.go
new file mode 100644
index 0000000..23cc07c
--- /dev/null
+++ b/go/src/examples/advertiser/client/scanner.go
@@ -0,0 +1,132 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"fmt"
+	"log"
+	"strings"
+
+	"mojo/public/go/application"
+	"mojo/public/go/bindings"
+	"mojo/public/go/system"
+
+	v23 "v.io/x/mojo/client"
+
+	"mojom/examples/echo"
+	"mojom/vanadium/discovery"
+)
+
+//#include "mojo/public/c/system/types.h"
+import "C"
+
+type handler struct {
+	ch chan string
+}
+
+func (h *handler) Found(s discovery.Service) error {
+	log.Println("found ", s)
+	h.ch <- s.Addrs[0]
+	return nil
+}
+
+func (h *handler) Lost(s string) error {
+	log.Println("Lost ", s)
+	return nil
+}
+
+type RemoteEchoClientDelegate struct {
+}
+
+func (delegate *RemoteEchoClientDelegate) findService(ctx application.Context) (string, error) {
+	r, p := discovery.CreateMessagePipeForScanner()
+	ctx.ConnectToApplication("https://mojo.v.io/scanner.mojO").ConnectToService(&r)
+	scanner := discovery.NewScannerProxy(p, bindings.GetAsyncWaiter())
+	scanReq, scanPtr := discovery.CreateMessagePipeForScanHandler()
+	ch := make(chan string)
+	stub := discovery.NewScanHandlerStub(scanReq, &handler{ch: ch}, bindings.GetAsyncWaiter())
+	id, e1, e2 := scanner.Scan(`v.InterfaceName="mojo.examples.echo.RemoteEcho"`, scanPtr)
+	if e1 != nil {
+		return "", fmt.Errorf("%s", e1.Msg)
+	}
+
+	if e2 != nil {
+		return "", e2
+	}
+	go func() {
+		err := stub.ServeRequest()
+		if err != nil {
+			log.Println("failed to get result", err)
+			ch <- ""
+		}
+		scanner.Stop(id)
+		stub.Close()
+	}()
+	res := <-ch
+	return res, nil
+}
+
+// When running echo_client, ctx.Args() should contain:
+// 0: mojo app name
+// 1: remote endpoint
+// 2+: string to echo
+func (delegate *RemoteEchoClientDelegate) Initialize(ctx application.Context) {
+	log.Printf("RemoteEchoClientDelegate.Initialize...")
+
+	remoteEndpoint, err := delegate.findService(ctx)
+	if err != nil {
+		log.Println("Failed to start get address:", err)
+		return
+	}
+
+	// Parse arguments. Note: May panic if not enough args are given.
+	echoString := "Hello, Go world!"
+	if len(ctx.Args()) > 1 {
+		echoString = strings.Join(ctx.Args()[1:], " ")
+	}
+
+	r, p := echo.CreateMessagePipeForRemoteEcho()
+
+	v23.ConnectToRemoteService(ctx, &r, remoteEndpoint)
+	echoProxy := echo.NewRemoteEchoProxy(p, bindings.GetAsyncWaiter())
+
+	log.Printf("RemoteEchoClientDelegate.Initialize calling EchoString...")
+	response, err := echoProxy.EchoString(echoString)
+	if err == nil {
+		fmt.Printf("client: %s\n", response)
+	} else {
+		log.Println(err)
+	}
+
+	log.Printf("RemoteEchoClientDelegate.Initialize calling EchoX...")
+	response2, err := echoProxy.EchoX([]bool{true, false, false, true}, echo.AInArg{"A String"})
+	if err == nil {
+		fmt.Printf("client: %v\n", response2)
+	} else {
+		log.Println("Error: ", err)
+	}
+
+	fmt.Printf("(done)\n")
+	echoProxy.Close_Proxy()
+	ctx.Close()
+}
+
+func (delegate *RemoteEchoClientDelegate) AcceptConnection(connection *application.Connection) {
+	log.Printf("RemoteEchoClientDelegate.AcceptConnection...")
+	connection.Close()
+}
+
+func (delegate *RemoteEchoClientDelegate) Quit() {
+	log.Printf("RemoteEchoClientDelegate.Quit...")
+}
+
+//export MojoMain
+func MojoMain(handle C.MojoHandle) C.MojoResult {
+	application.Run(&RemoteEchoClientDelegate{}, system.MojoHandle(handle))
+	return C.MOJO_RESULT_OK
+}
+
+func main() {
+}
diff --git a/go/src/examples/advertiser/server/advertiser.go b/go/src/examples/advertiser/server/advertiser.go
new file mode 100644
index 0000000..9bf6f99
--- /dev/null
+++ b/go/src/examples/advertiser/server/advertiser.go
@@ -0,0 +1,106 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"log"
+
+	"mojo/public/go/application"
+	"mojo/public/go/bindings"
+	"mojo/public/go/system"
+
+	"mojom/examples/echo"
+	"mojom/v23proxy"
+)
+
+//#include "mojo/public/c/system/types.h"
+import "C"
+
+type RemoteEchoImpl struct{}
+
+// Note: This is pretty much identical to echo_server.go, except for the name changes.
+func (re *RemoteEchoImpl) EchoString(inValue string) (outValue string, err error) {
+	log.Printf("server EchoString: %s\n", inValue)
+	return inValue, nil
+}
+
+func (re *RemoteEchoImpl) EchoX(inArg1 []bool, inArg2 echo.AInArg) (out echo.OutArgTypes, err error) {
+	log.Printf("server EchoX: arg1: %v arg2: %v\n", inArg1, inArg2)
+	return &echo.OutArgTypesRes{echo.Result_B}, nil
+}
+
+type RemoteEchoServerDelegate struct {
+	remoteEchoFactory RemoteEchoFactory
+	instanceId        *string
+	proxy             *v23proxy.Advertiser_Proxy
+}
+
+type RemoteEchoFactory struct {
+	stubs []*bindings.Stub
+}
+
+func (delegate *RemoteEchoServerDelegate) Initialize(context application.Context) {
+	log.Printf("RemoteEchoServerDelegate.Initialize...")
+	req, ptr := v23proxy.CreateMessagePipeForAdvertiser()
+	context.ConnectToApplication("https://mojo.v.io/v23proxy.mojo").ConnectToService(&req)
+	delegate.proxy = v23proxy.NewAdvertiserProxy(ptr, bindings.GetAsyncWaiter())
+	mService := v23proxy.Service{
+		InterfaceName: "mojo.examples.echo.RemoteEcho",
+		Url:           "https://mojo.v.io/echo_server_discovery.mojo/mojo::examples::RemoteEcho",
+	}
+	var err1 *string
+	var err error
+	delegate.instanceId, err1, err = delegate.proxy.Advertise(mService, nil)
+	if err != nil || err1 != nil {
+		var errMessage string
+		if err1 != nil {
+			errMessage = *err1
+		}
+		log.Println("Failed to advertise with", errMessage, err)
+	}
+}
+
+func (remoteEchoFactory *RemoteEchoFactory) Create(request echo.RemoteEcho_Request) {
+	log.Printf("RemoteEchoServer's RemoteEchoFactory.Create...")
+	stub := echo.NewRemoteEchoStub(request, &RemoteEchoImpl{}, bindings.GetAsyncWaiter())
+	remoteEchoFactory.stubs = append(remoteEchoFactory.stubs, stub)
+	go func() {
+		for {
+			if err := stub.ServeRequest(); err != nil {
+				connectionError, ok := err.(*bindings.ConnectionError)
+				if !ok || !connectionError.Closed() {
+					log.Println(err)
+				}
+				break
+			}
+		}
+	}()
+}
+
+func (delegate *RemoteEchoServerDelegate) AcceptConnection(connection *application.Connection) {
+	log.Printf("RemoteEchoServerDelegate.AcceptConnection...")
+	connection.ProvideServicesWithDescriber(
+		&echo.RemoteEcho_ServiceFactory{&delegate.remoteEchoFactory},
+	)
+}
+
+func (delegate *RemoteEchoServerDelegate) Quit() {
+	log.Printf("RemoteEchoServerDelegate.Quit...")
+	for _, stub := range delegate.remoteEchoFactory.stubs {
+		stub.Close()
+	}
+	if delegate.instanceId != nil {
+		delegate.proxy.StopAdvertising(*delegate.instanceId)
+	}
+}
+
+//export MojoMain
+func MojoMain(handle C.MojoHandle) C.MojoResult {
+	application.Run(&RemoteEchoServerDelegate{}, system.MojoHandle(handle))
+	return C.MOJO_RESULT_OK
+}
+
+func main() {
+}
diff --git a/go/src/v.io/x/mojo/proxy/proxy.go b/go/src/v.io/x/mojo/proxy/proxy.go
index bcf27f1..a3e994d 100644
--- a/go/src/v.io/x/mojo/proxy/proxy.go
+++ b/go/src/v.io/x/mojo/proxy/proxy.go
@@ -6,6 +6,7 @@
 
 import (
 	"fmt"
+	"sync"
 
 	"v.io/v23"
 	"v.io/v23/context"
@@ -227,7 +228,7 @@
 	advertisementMap map[string]uint32
 }
 
-func (d *advertiser) Advertise(s Service, visibility []string) (*string, *string, error) {
+func (d *advertiser) Advertise(s v23proxy.Service, visibility []string) (*string, *string, error) {
 	mService := discovery.Service{
 		InstanceId:    s.InstanceId,
 		InstanceName:  s.InstanceName,
@@ -236,9 +237,9 @@
 	}
 	mService.Addrs = make([]string, len(d.endpoints))
 	for i, ep := range d.endpoints {
-		mService.Addrs[i] = ep + "//" + s.url
+		mService.Addrs[i] = ep + "//" + s.Url
 	}
-	handle, instance, mErr, err := d.advProxy.Advertise(mService, visibility)
+	handle, instance, mErr, err := d.advProxy.Advertise(mService, &visibility)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -262,9 +263,11 @@
 	if found {
 		d.advProxy.Stop(id)
 	}
+	return nil
 }
 
 type discoveryFactory struct {
+	ctx        *context.T
 	appContext application.Context
 	eps        []string
 	stubs      []*bindings.Stub
@@ -274,7 +277,7 @@
 	req, ptr := discovery.CreateMessagePipeForAdvertiser()
 	df.appContext.ConnectToApplication("https://mojo.v.io/discovery.mojo").ConnectToService(&req)
 	d := &advertiser{
-		endpoints:        eps,
+		endpoints:        df.eps,
 		advProxy:         discovery.NewAdvertiserProxy(ptr, bindings.GetAsyncWaiter()),
 		advertisementMap: map[string]uint32{},
 	}
@@ -287,7 +290,7 @@
 		if err := advertiserStub.ServeRequest(); err != nil {
 			connectionError, ok := err.(*bindings.ConnectionError)
 			if !ok || !connectionError.Closed() {
-				delegate.ctx.Errorf("%v", err)
+				df.ctx.Errorf("%v", err)
 			}
 			return
 		}
@@ -330,6 +333,7 @@
 	status := s.Status()
 	fmt.Println("Listening at:", status.Endpoints[0].Name())
 	delegate.df = &discoveryFactory{
+		ctx:        ctx,
 		appContext: context,
 	}
 	delegate.df.eps = make([]string, len(status.Endpoints))
diff --git a/mojom/mojom/v23proxy.mojom b/mojom/mojom/v23proxy.mojom
index 91ff8e0..e703b35 100644
--- a/mojom/mojom/v23proxy.mojom
+++ b/mojom/mojom/v23proxy.mojom
@@ -53,5 +53,5 @@
   // E.g., {'resolution': '1024x768'}.
   map<string, string>? Attrs;
   // The url of the advertising mojo service
-  string url;
+  string Url;
 };