first cut.

Change-Id: I71970188e1ee7d3c519bfe46528704d2f506302c
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..81feab8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+
+include ../shared/mojo.mk
+
+
+go/src/mojom/vanadium/discovery/discovery.mojom.go: mojom/vanadium/discovery.mojom | mojo-env-check
+	$(call MOJOM_GEN,$<,.,go)
+	gofmt -w $@
\ No newline at end of file
diff --git a/go/src/vanadium/discovery/discovery.go b/go/src/vanadium/discovery/discovery.go
new file mode 100644
index 0000000..0446f22
--- /dev/null
+++ b/go/src/vanadium/discovery/discovery.go
@@ -0,0 +1,88 @@
+package discovery
+
+import (
+	mojom "mojom/vanadium/discovery"
+	"v.io/v23/discovery"
+	"sync"
+	"v.io/v23/context"
+	"v.io/v23/security/access"
+	"v.io/v23/verror"
+	"mojo/public/go/bindings"
+)
+
+type discoveryService struct {
+	mu sync.Mutex
+	ctx *context.T
+	s discovery.T
+	nextAdv int32
+	pendingAdvs map[int32]chan struct{}
+	nextScan int32;
+	pendingScans map[int32]chan struct{}
+
+}
+
+
+func converToErrorStruct(err error) *mojom.Error {
+	outErr := &mojom.Error{
+			Id: "v.io/verror/Unknown",
+			Msg: err.Error(),
+		}
+		if e, ok := err.(verror.E); ok {
+			outErr.Id = string(e.ID)
+			outErr.Action = int32(e.Action)
+		}
+	return outErr
+}
+
+func (d *discoveryService) Advertisement(s mojom.Service, patterns []string) (int32, *mojom.Error) {
+	vService := discovery.Service{
+		InstanceUuid: s.InstanceUuid,
+		InterfaceName: s.InterfaceName,
+		Attrs: discovery.Attributes(s.Attrs),
+		Addrs: s.Addrs,
+	}
+
+	ctx, c := context.WithCancel(d.ctx)
+
+	err := d.s.Advertise(ctx, vService, access.Permissions{})
+	if err != nil {
+		return 0, converToErrorStruct(err)
+	}
+	ch := make(chan struct{})
+	d.mu.Lock()
+	id := d.nextAdv
+	d.pendingAdvs[id] = ch
+	d.nextAdv++
+	d.mu.Unlock()
+	go func() {
+		<-ch
+		c()
+	}()
+	return id, nil
+}
+
+func (d *discoveryService) StopAdvertising(handle int32) {
+	d.mu.Lock()
+	ch := d.pendingAdvs[handle]
+	d.mu.Unlock()
+	if ch != nil {
+		close(ch)
+	}
+}
+
+func (d *discoveryService) Scan(query string, scanHandler mojom.ScanHandler_Pointer) (int32, *mojom.Error)  {
+	ctx, c := context.WithCancel(d.ctx)
+	proxy := mojom.NewScanHandlerProxy(scanHandler, bindings.GetAsyncWaiter())
+	scanCh, err := d.s.Scan(ctx, query)
+	go func() {
+		for v := range scanCh {
+			switch v.Interface().(type) {
+			case discovery.UpdateFound
+			}
+			if v.Index() == 0 {
+				v.
+				proxy.Found()
+			}
+		}
+	}()
+}
diff --git a/mojom/vanadium/discovery.mojom b/mojom/vanadium/discovery.mojom
new file mode 100644
index 0000000..996c3a6
--- /dev/null
+++ b/mojom/vanadium/discovery.mojom
@@ -0,0 +1,39 @@
+module discovery;
+
+// Copied from v.io/v23/discovery/types.vdl
+struct Service {
+    // The 128 bit (16 byte) universal unique identifier of a service instance.
+	// If this is not specified, a random UUID will be used.
+	array<uint8> InstanceUuid;
+	// The interface that the service implements.
+	// E.g., 'v.io/v23/services/vtrace.Store'.
+	string InterfaceName;
+	// The service attributes.
+	// E.g., {'resolution': '1024x768'}.
+	map<string, string> Attrs;
+	// The addresses that the service is served on.
+	// E.g., '/host:port/a/b/c'.
+	array<string> Addrs;
+};
+
+struct Error {
+   string id;
+   int32 action;
+   string msg;
+};
+
+interface Discoverer {
+	Advertise(Service s, array<string> pattern) => (int32 Handle, Error? Err);
+
+	StopAdvertising(int32 h);
+
+	Scan(string query, ScanHandler scanHandler) => (int32 Handle, Error? Err);
+
+	StopScan(int32 h);
+};
+
+interface ScanHandler {
+	Found(Service s);
+
+	Lost(Service s);
+};
\ No newline at end of file