veyron2/security,veyron/security/caveat: Expose Endpoint in security.Context; implement NetworkType caveat

Change-Id: Ie64f97e5e1c2179515760396747375ec2c54ccf5
diff --git a/examples/boxes/android/src/boxesp2p/main.go b/examples/boxes/android/src/boxesp2p/main.go
index e2359d9..90cae68 100644
--- a/examples/boxes/android/src/boxesp2p/main.go
+++ b/examples/boxes/android/src/boxesp2p/main.go
@@ -135,7 +135,7 @@
 
 func (gs *goState) SyncBoxes(context ipc.ServerContext) error {
 	// Get the endpoint of the remote process
-	endPt, err := inaming.NewEndpoint(context.RemoteAddr().String())
+	endPt, err := inaming.NewEndpoint(context.RemoteEndpoint().String())
 	if err != nil {
 		return err
 	}
diff --git a/runtimes/google/ipc/flow_test.go b/runtimes/google/ipc/flow_test.go
index 35f7662..e856eb3 100644
--- a/runtimes/google/ipc/flow_test.go
+++ b/runtimes/google/ipc/flow_test.go
@@ -10,6 +10,7 @@
 
 	_ "veyron/lib/testutil"
 	"veyron2/ipc"
+	"veyron2/naming"
 	"veyron2/security"
 	"veyron2/verror"
 )
@@ -31,6 +32,8 @@
 func (f *testFlow) Write(b []byte) (int, error)        { return f.w.Write(b) }
 func (f *testFlow) LocalAddr() net.Addr                { return nil }
 func (f *testFlow) RemoteAddr() net.Addr               { return nil }
+func (f *testFlow) LocalEndpoint() naming.Endpoint     { return nil }
+func (f *testFlow) RemoteEndpoint() naming.Endpoint    { return nil }
 func (f *testFlow) LocalID() security.PublicID         { return security.FakePublicID("test") }
 func (f *testFlow) RemoteID() security.PublicID        { return security.FakePublicID("test") }
 func (f *testFlow) SetReadDeadline(t time.Time) error  { return nil }
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index 5cf77d8..3c0842c 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -3,7 +3,6 @@
 import (
 	"fmt"
 	"io"
-	"net"
 	"reflect"
 	"strings"
 	"sync"
@@ -574,8 +573,8 @@
 func (fs *flowServer) RemoteID() security.PublicID                   { return fs.authorizedRemoteID }
 func (fs *flowServer) Deadline() time.Time                           { return fs.deadline }
 func (fs *flowServer) Blessing() security.PublicID                   { return fs.blessing }
-func (fs *flowServer) LocalAddr() net.Addr                           { return fs.flow.LocalAddr() }
-func (fs *flowServer) RemoteAddr() net.Addr                          { return fs.flow.RemoteAddr() }
+func (fs *flowServer) LocalEndpoint() naming.Endpoint                { return fs.flow.LocalEndpoint() }
+func (fs *flowServer) RemoteEndpoint() naming.Endpoint               { return fs.flow.RemoteEndpoint() }
 
 func (fs *flowServer) IsClosed() bool {
 	return fs.flow.IsClosed()
diff --git a/runtimes/google/ipc/stream/vc/flow.go b/runtimes/google/ipc/stream/vc/flow.go
index 9a9112e..ccad460 100644
--- a/runtimes/google/ipc/stream/vc/flow.go
+++ b/runtimes/google/ipc/stream/vc/flow.go
@@ -4,6 +4,7 @@
 	"net"
 	"time"
 
+	"veyron2/naming"
 	"veyron2/security"
 )
 
@@ -11,7 +12,7 @@
 	idHolder
 	*reader
 	*writer
-	laddr, raddr net.Addr
+	localEndpoint, remoteEndpoint naming.Endpoint
 }
 
 type idHolder interface {
@@ -19,8 +20,12 @@
 	RemoteID() security.PublicID
 }
 
-func (f *flow) LocalAddr() net.Addr  { return f.laddr }
-func (f *flow) RemoteAddr() net.Addr { return f.raddr }
+func (f *flow) LocalEndpoint() naming.Endpoint  { return f.localEndpoint }
+func (f *flow) RemoteEndpoint() naming.Endpoint { return f.remoteEndpoint }
+
+// implement net.Conn
+func (f *flow) LocalAddr() net.Addr  { return f.localEndpoint }
+func (f *flow) RemoteAddr() net.Addr { return f.remoteEndpoint }
 func (f *flow) Close() error {
 	f.reader.Close()
 	f.writer.Close()
diff --git a/runtimes/google/ipc/stream/vc/listener_test.go b/runtimes/google/ipc/stream/vc/listener_test.go
index 269c366..a449242 100644
--- a/runtimes/google/ipc/stream/vc/listener_test.go
+++ b/runtimes/google/ipc/stream/vc/listener_test.go
@@ -5,6 +5,7 @@
 	"testing"
 	"time"
 
+	"veyron2/naming"
 	"veyron2/security"
 )
 
@@ -17,6 +18,8 @@
 func (*noopFlow) IsClosed() bool                     { return false }
 func (*noopFlow) Closed() <-chan struct{}            { return nil }
 func (*noopFlow) Cancel()                            {}
+func (*noopFlow) LocalEndpoint() naming.Endpoint     { return nil }
+func (*noopFlow) RemoteEndpoint() naming.Endpoint    { return nil }
 func (*noopFlow) LocalAddr() net.Addr                { return nil }
 func (*noopFlow) RemoteAddr() net.Addr               { return nil }
 func (*noopFlow) SetDeadline(t time.Time) error      { return nil }
diff --git a/runtimes/google/ipc/stream/vc/vc.go b/runtimes/google/ipc/stream/vc/vc.go
index f213412..09d719d 100644
--- a/runtimes/google/ipc/stream/vc/vc.go
+++ b/runtimes/google/ipc/stream/vc/vc.go
@@ -154,11 +154,11 @@
 		return nil, fmt.Errorf("failed to create writer for Flow: %v", err)
 	}
 	f := &flow{
-		idHolder: vc,
-		reader:   newReader(readHandlerImpl{vc, fid}),
-		writer:   writer,
-		laddr:    vc.localEP,
-		raddr:    vc.remoteEP,
+		idHolder:       vc,
+		reader:         newReader(readHandlerImpl{vc, fid}),
+		writer:         writer,
+		localEndpoint:  vc.localEP,
+		remoteEndpoint: vc.remoteEP,
 	}
 	vc.mu.Lock()
 	if vc.flowMap != nil {
@@ -257,11 +257,11 @@
 		return fmt.Errorf("failed to create writer for new flow(%d): %v", fid, err)
 	}
 	f := &flow{
-		idHolder: vc,
-		reader:   newReader(readHandlerImpl{vc, fid}),
-		writer:   writer,
-		laddr:    vc.localEP,
-		raddr:    vc.remoteEP,
+		idHolder:       vc,
+		reader:         newReader(readHandlerImpl{vc, fid}),
+		writer:         writer,
+		localEndpoint:  vc.localEP,
+		remoteEndpoint: vc.remoteEP,
 	}
 	if err = vc.listener.Enqueue(f); err != nil {
 		f.Shutdown()
diff --git a/runtimes/google/security/util.go b/runtimes/google/security/util.go
index be2c7a2..754a5f8 100644
--- a/runtimes/google/security/util.go
+++ b/runtimes/google/security/util.go
@@ -7,6 +7,7 @@
 	"strings"
 
 	"veyron/runtimes/google/security/keys"
+	"veyron2/naming"
 	"veyron2/security"
 	"veyron2/security/wire"
 )
@@ -91,6 +92,8 @@
 	Suffix string
 	// Label is the security label of the method being invoked.
 	Label security.Label
+	// LocalEndpoint, RemoteEndpoint are the veyron endpoints of the local and remote ends of a request
+	LocalEndpoint, RemoteEndpoint naming.Endpoint
 }
 
 // context implements security.Context. This implementation simply stores the
@@ -141,6 +144,8 @@
 func (c *context) CaveatDischarges() security.CaveatDischargeMap { return c.ContextArgs.Discharges }
 func (c *context) LocalID() security.PublicID                    { return c.ContextArgs.LocalID }
 func (c *context) RemoteID() security.PublicID                   { return c.ContextArgs.RemoteID }
+func (c *context) LocalEndpoint() naming.Endpoint                { return c.ContextArgs.LocalEndpoint }
+func (c *context) RemoteEndpoint() naming.Endpoint               { return c.ContextArgs.RemoteEndpoint }
 
 // NewContext returns a new security.Context for the provided method, name,
 // suffix, discharges, label and identities of the local and remote principals
diff --git a/security/caveat/caveat.go b/security/caveat/caveat.go
index 6cb4735..a0e0f11 100644
--- a/security/caveat/caveat.go
+++ b/security/caveat/caveat.go
@@ -59,8 +59,20 @@
 	return fmt.Errorf("%#v forbids RPCing with peer %s", c, ctx.LocalID())
 }
 
+// NetworkType is a security.Caveat that restricts communication with the
+// remote process to a particular network ("tcp", "udp", "bluetooth" etc.)
+type NetworkType string
+
+func (cav NetworkType) Validate(ctx security.Context) error {
+	if ctx.RemoteEndpoint().Addr().Network() == string(cav) {
+		return nil
+	}
+	return fmt.Errorf("required network type %q, got %q", cav, ctx.RemoteEndpoint().Addr().Network())
+}
+
 func init() {
 	vom.Register(Expiry{})
 	vom.Register(MethodRestriction(nil))
 	vom.Register(PeerIdentity(nil))
+	vom.Register(NetworkType(""))
 }
diff --git a/security/caveat/caveat_test.go b/security/caveat/caveat_test.go
index 8c7efdf..b4f44f8 100644
--- a/security/caveat/caveat_test.go
+++ b/security/caveat/caveat_test.go
@@ -1,16 +1,27 @@
 package caveat_test
 
 import (
+	"net"
 	"testing"
 	"time"
 
 	"veyron/security/caveat"
+	"veyron2/naming"
 	"veyron2/security"
 )
 
+// endpoint implements naming.Endpoint
+type endpoint struct {
+	naming.Endpoint
+	addr net.Addr
+}
+
+func (e endpoint) Addr() net.Addr { return e.addr }
+
 type context struct {
-	local, remote security.PublicID
-	method        string
+	local, remote                 security.PublicID
+	localEndpoint, remoteEndpoint endpoint
+	method                        string
 }
 
 func (c *context) Method() string                                { return c.method }
@@ -20,6 +31,8 @@
 func (c *context) CaveatDischarges() security.CaveatDischargeMap { return nil }
 func (c *context) LocalID() security.PublicID                    { return c.local }
 func (c *context) RemoteID() security.PublicID                   { return c.remote }
+func (c *context) LocalEndpoint() naming.Endpoint                { return &c.localEndpoint }
+func (c *context) RemoteEndpoint() naming.Endpoint               { return &c.remoteEndpoint }
 
 func TestCaveats(t *testing.T) {
 	var (
@@ -34,6 +47,8 @@
 		{&caveat.Expiry{IssueTime: now, ExpiryTime: now.Add(time.Hour)}, true},
 		{&caveat.Expiry{IssueTime: now.Add(-1 * time.Hour), ExpiryTime: now.Add(-1 * time.Minute)}, false},
 		{caveat.MethodRestriction(nil), false},
+		{caveat.NetworkType("udp"), false},
+		{caveat.NetworkType("tcp"), true},
 		{caveat.MethodRestriction{"Pause", "Play"}, true},
 		{caveat.MethodRestriction{"List"}, false},
 		{caveat.PeerIdentity(nil), false},
@@ -41,7 +56,7 @@
 		{caveat.PeerIdentity{"fake/carol"}, false},
 		{caveat.PeerIdentity{"fake/alice", "fake/carol"}, true},
 	}
-	ctx := &context{local: alice, remote: bob, method: "Play"}
+	ctx := &context{local: alice, remote: bob, method: "Play", remoteEndpoint: endpoint{addr: &net.TCPAddr{}}}
 	for _, test := range tests {
 		if err := test.c.Validate(ctx); test.ok != (err == nil) {
 			t.Errorf("Caveat:%#v. Got error:%v, want error:%v", test.c, err, test.ok)
diff --git a/services/store/memstore/blackbox/util.go b/services/store/memstore/blackbox/util.go
index c46baf0..2ff6bf1 100644
--- a/services/store/memstore/blackbox/util.go
+++ b/services/store/memstore/blackbox/util.go
@@ -4,7 +4,6 @@
 	"fmt"
 	"io"
 	"io/ioutil"
-	"net"
 	"os"
 	"runtime"
 	"testing"
@@ -16,6 +15,7 @@
 	"veyron/services/store/service"
 
 	"veyron2/ipc"
+	"veyron2/naming"
 	"veyron2/security"
 	"veyron2/services/watch"
 	"veyron2/storage"
@@ -66,11 +66,11 @@
 	return nil
 }
 
-func (rootContext) LocalAddr() net.Addr {
+func (rootContext) LocalEndpoint() naming.Endpoint {
 	return nil
 }
 
-func (rootContext) RemoteAddr() net.Addr {
+func (rootContext) RemoteEndpoint() naming.Endpoint {
 	return nil
 }
 
diff --git a/services/store/memstore/util_test.go b/services/store/memstore/util_test.go
index 0917a4a..9a344a8 100644
--- a/services/store/memstore/util_test.go
+++ b/services/store/memstore/util_test.go
@@ -2,7 +2,6 @@
 
 import (
 	"io"
-	"net"
 	"runtime"
 	"testing"
 	"time"
@@ -11,6 +10,7 @@
 	"veyron/services/store/service"
 
 	"veyron2/ipc"
+	"veyron2/naming"
 	"veyron2/security"
 	"veyron2/storage"
 )
@@ -60,11 +60,11 @@
 	return nil
 }
 
-func (*cancellableContext) LocalAddr() net.Addr {
+func (*cancellableContext) LocalEndpoint() naming.Endpoint {
 	return nil
 }
 
-func (*cancellableContext) RemoteAddr() net.Addr {
+func (*cancellableContext) RemoteEndpoint() naming.Endpoint {
 	return nil
 }
 
diff --git a/services/store/memstore/watch/testing/util.go b/services/store/memstore/watch/testing/util.go
index 02a7365..941a2a6 100644
--- a/services/store/memstore/watch/testing/util.go
+++ b/services/store/memstore/watch/testing/util.go
@@ -2,11 +2,11 @@
 
 import (
 	"errors"
-	"net"
 	"sync"
 	"time"
 
 	"veyron2/ipc"
+	"veyron2/naming"
 	"veyron2/security"
 	"veyron2/services/watch"
 )
@@ -65,11 +65,11 @@
 	return nil
 }
 
-func (*CancellableContext) LocalAddr() net.Addr {
+func (*CancellableContext) LocalEndpoint() naming.Endpoint {
 	return nil
 }
 
-func (*CancellableContext) RemoteAddr() net.Addr {
+func (*CancellableContext) RemoteEndpoint() naming.Endpoint {
 	return nil
 }
 
diff --git a/services/store/server/server_test.go b/services/store/server/server_test.go
index bfdabd4..b434767 100644
--- a/services/store/server/server_test.go
+++ b/services/store/server/server_test.go
@@ -4,7 +4,6 @@
 	"fmt"
 	"io/ioutil"
 	"log"
-	"net"
 	"os"
 	"reflect"
 	"testing"
@@ -14,6 +13,7 @@
 	"veyron/services/store/raw"
 
 	"veyron2/ipc"
+	"veyron2/naming"
 	"veyron2/security"
 	"veyron2/services/store"
 	"veyron2/services/watch"
@@ -72,11 +72,11 @@
 	return nil
 }
 
-func (*testContext) LocalAddr() net.Addr {
+func (*testContext) LocalEndpoint() naming.Endpoint {
 	return nil
 }
 
-func (*testContext) RemoteAddr() net.Addr {
+func (*testContext) RemoteEndpoint() naming.Endpoint {
 	return nil
 }