Merge "veyron/runtimes/google/ipc/stream/vif: Handle caching of VIFs over unix sockets correctly."
diff --git a/runtimes/google/ipc/stream/vif/set.go b/runtimes/google/ipc/stream/vif/set.go
index c4b28ce..6ecbe60 100644
--- a/runtimes/google/ipc/stream/vif/set.go
+++ b/runtimes/google/ipc/stream/vif/set.go
@@ -25,6 +25,14 @@
// If there are multiple VIFs established to the same remote network address,
// Find will randomly return one of them.
func (s *Set) Find(network, address string) *VIF {
+ if len(address) == 0 || (network == "pipe" && address == "pipe") {
+ // Some network connections (like those created with net.Pipe
+ // or Unix sockets) do not end up with distinct conn.RemoteAddrs
+ // on distinct net.Conns. For those cases, avoid the cache collisions
+ // by disabling cache lookups for them.
+ return nil
+ }
+
s.mu.RLock()
defer s.mu.RUnlock()
l, ok := s.set[s.key(network, address)]
diff --git a/runtimes/google/ipc/stream/vif/set_test.go b/runtimes/google/ipc/stream/vif/set_test.go
new file mode 100644
index 0000000..e704cb3
--- /dev/null
+++ b/runtimes/google/ipc/stream/vif/set_test.go
@@ -0,0 +1,84 @@
+package vif_test
+
+import (
+ "io/ioutil"
+ "net"
+ "path"
+ "testing"
+
+ "veyron2/naming"
+
+ "veyron/runtimes/google/ipc/stream/vif"
+)
+
+func TestSetWithPipes(t *testing.T) {
+ var (
+ conn1, _ = net.Pipe()
+ conn2, _ = net.Pipe()
+ addr1 = conn1.RemoteAddr()
+ addr2 = conn2.RemoteAddr()
+
+ vf, err = vif.InternalNewDialedVIF(conn1, naming.FixedRoutingID(1), nil)
+ set = vif.NewSet()
+ )
+ if err != nil {
+ t.Fatal(err)
+ }
+ if addr1.Network() != addr2.Network() || addr1.String() != addr2.String() {
+ t.Fatalf("This test was intended for distinct connections that have duplicate RemoteAddrs. "+
+ "That does not seem to be the case with (%q, %q) and (%q, %q)",
+ addr1.Network(), addr1, addr2.Network(), addr2)
+ }
+ set.Insert(vf)
+ if found := set.Find(addr2.Network(), addr2.String()); found != nil {
+ t.Fatalf("Got [%v] want nil on Find(%q, %q))", found, addr2.Network(), addr2)
+ }
+}
+
+func TestSetWithUnixSocket(t *testing.T) {
+ dir, err := ioutil.TempDir("", "TestSetWithFileConn")
+ if err != nil {
+ t.Fatal(err)
+ }
+ sockname := path.Join(dir, "socket")
+ ln, err := net.Listen("unix", sockname)
+ if err != nil {
+ t.Fatal(err)
+ }
+ // Setup the creation of two separate connections.
+ // At the listener, they will end up with two distinct connections
+ // with the same "address" (empty string).
+ go func() {
+ for i := 0; i < 2; i++ {
+ if _, err := net.Dial("unix", sockname); err != nil {
+ ln.Close()
+ t.Fatal(err)
+ }
+ }
+ }()
+
+ conn1, err := ln.Accept()
+ if err != nil {
+ t.Fatal(err)
+ }
+ conn2, err := ln.Accept()
+ if err != nil {
+ t.Fatal(err)
+ }
+ addr1 := conn1.RemoteAddr()
+ addr2 := conn2.RemoteAddr()
+ if addr1.Network() != addr2.Network() || addr1.String() != addr2.String() {
+ t.Fatalf("This test was intended for distinct connections that have duplicate RemoteAddrs. "+
+ "That does not seem to be the case with (%q, %q) and (%q, %q)",
+ addr1.Network(), addr1, addr2.Network(), addr2)
+ }
+ vif1, err := vif.InternalNewAcceptedVIF(conn1, naming.FixedRoutingID(1), nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ set := vif.NewSet()
+ set.Insert(vif1)
+ if found := set.Find(addr2.Network(), addr2.String()); found != nil {
+ t.Errorf("Got [%v] want nil on Find(%q, %q)", found, addr2.Network(), addr2)
+ }
+}