Exemple #1
0
// managedConnectNewPeer connects to peers >= v1.0.0. The peer is added as a
// node and a peer. The peer is only added if a nil error is returned.
func (g *Gateway) managedConnectNewPeer(conn net.Conn, remoteVersion string, remoteAddr modules.NetAddress) error {
	g.mu.RLock()
	port := g.port
	g.mu.RUnlock()
	// Send our dialable address to the peer so they can dial us back should we
	// disconnect.
	err := connectPortHandshake(conn, port)
	if err != nil {
		return err
	}

	g.mu.Lock()
	defer g.mu.Unlock()

	err = g.addNode(remoteAddr)
	if err != nil && err != errNodeExists {
		return err
	}
	err = g.save()
	if err != nil {
		return fmt.Errorf("error saving node list: %v", err)
	}

	g.addPeer(&peer{
		Peer: modules.Peer{
			NetAddress: remoteAddr,
			Inbound:    false,
			Version:    remoteVersion,
		},
		sess: muxado.Client(conn),
	})
	return nil
}
Exemple #2
0
// managedConnectNewPeer connects to peers >= v1.0.0. The peer is added as a
// node and a peer. The peer is only added if a nil error is returned.
func (g *Gateway) managedConnectNewPeer(conn net.Conn, remoteVersion string, remoteAddr modules.NetAddress) error {
	g.mu.RLock()
	port := g.port
	g.mu.RUnlock()
	// Send our dialable address to the peer so they can dial us back should we
	// disconnect.
	err := connectPortHandshake(conn, port)
	if err != nil {
		return err
	}

	// Attempt to add the peer to the node list. If the add is successful and
	// the address is a local address, mark the peer as a local peer.
	local := false
	err = g.managedAddUntrustedNode(remoteAddr)
	if err != nil && remoteAddr.IsLocal() {
		local = true
	}

	g.mu.Lock()
	defer g.mu.Unlock()
	g.addPeer(&peer{
		Peer: modules.Peer{
			Inbound:    false,
			Local:      local,
			NetAddress: remoteAddr,
			Version:    remoteVersion,
		},
		sess: muxado.Client(conn),
	})
	return nil
}
Exemple #3
0
// TestRandomInbountPeer checks that randomOutboundPeer returns the correct
// peer.
func TestRandomOutboundPeer(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}

	g := newTestingGateway("TestRandomInboundPeer", t)
	defer g.Close()
	g.mu.Lock()
	defer g.mu.Unlock()
	_, err := g.randomOutboundPeer()
	if err != errNoPeers {
		t.Fatal("expected errNoPeers, got", err)
	}

	g.addPeer(&peer{
		Peer: modules.Peer{
			NetAddress: "foo.com:123",
			Inbound:    false,
		},
		sess: muxado.Client(new(dummyConn)),
	})
	if len(g.peers) != 1 {
		t.Fatal("gateway did not add peer")
	}
	addr, err := g.randomOutboundPeer()
	if err != nil || addr != "foo.com:123" {
		t.Fatal("gateway did not select random peer")
	}
}
Exemple #4
0
// TestAddPeer tries adding a peer to the gateway.
func TestAddPeer(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}

	g := newTestingGateway("TestAddPeer", t)
	defer g.Close()
	g.mu.Lock()
	defer g.mu.Unlock()
	g.addPeer(&peer{
		Peer: modules.Peer{
			NetAddress: "foo.com:123",
		},
		sess: muxado.Client(new(dummyConn)),
	})
	if len(g.peers) != 1 {
		t.Fatal("gateway did not add peer")
	}
}
Exemple #5
0
// TestDisconnect checks that calls to gateway.Disconnect correctly disconnect
// and remove peers from the gateway.
func TestDisconnect(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}

	g := newTestingGateway("TestDisconnect", t)
	defer g.Close()

	if err := g.Disconnect("bar.com:123"); err == nil {
		t.Fatal("disconnect removed unconnected peer")
	}

	// dummy listener to accept connection
	l, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		t.Fatal("couldn't start listener:", err)
	}
	go func() {
		_, err := l.Accept()
		if err != nil {
			panic(err)
		}
	}()
	// skip standard connection protocol
	conn, err := net.Dial("tcp", l.Addr().String())
	if err != nil {
		t.Fatal("dial failed:", err)
	}
	g.mu.Lock()
	g.addPeer(&peer{
		Peer: modules.Peer{
			NetAddress: "foo.com:123",
		},
		sess: muxado.Client(conn),
	})
	g.mu.Unlock()
	if err := g.Disconnect("foo.com:123"); err != nil {
		t.Fatal("disconnect failed:", err)
	}
}
Exemple #6
0
// managedConnectOldPeer connects to peers < v1.0.0. The peer is added as a
// node and a peer. The peer is only added if a nil error is returned.
func (g *Gateway) managedConnectOldPeer(conn net.Conn, remoteVersion string, remoteAddr modules.NetAddress) error {
	// Attempt to add the peer to the node list. If the add is successful and
	// the address is a local address, mark the peer as a local peer.
	local := false
	err := g.managedAddUntrustedNode(remoteAddr)
	if err != nil && remoteAddr.IsLocal() {
		local = true
	}

	g.mu.Lock()
	defer g.mu.Unlock()
	g.addPeer(&peer{
		Peer: modules.Peer{
			Inbound:    false,
			Local:      local,
			NetAddress: remoteAddr,
			Version:    remoteVersion,
		},
		sess: muxado.Client(conn),
	})
	return nil
}
Exemple #7
0
// managedConnectOldPeer connects to peers < v1.0.0. The peer is added as a
// node and a peer. The peer is only added if a nil error is returned.
func (g *Gateway) managedConnectOldPeer(conn net.Conn, remoteVersion string, remoteAddr modules.NetAddress) error {
	g.mu.Lock()
	defer g.mu.Unlock()

	err := g.addNode(remoteAddr)
	if err != nil && err != errNodeExists {
		return err
	}
	err = g.save()
	if err != nil {
		return fmt.Errorf("error saving node list: %v", err)
	}

	g.addPeer(&peer{
		Peer: modules.Peer{
			NetAddress: remoteAddr,
			Inbound:    false,
			Version:    remoteVersion,
		},
		sess: muxado.Client(conn),
	})
	return nil
}
Exemple #8
0
// TestListen is a general test probling the connection listener.
func TestListen(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}

	g := newTestingGateway("TestListen", t)
	defer g.Close()

	// compliant connect with old version
	conn, err := net.Dial("tcp", string(g.Address()))
	if err != nil {
		t.Fatal("dial failed:", err)
	}
	addr := modules.NetAddress(conn.LocalAddr().String())
	ack, err := connectVersionHandshake(conn, "0.1")
	if err != errPeerRejectedConn {
		t.Fatal(err)
	}
	if ack != "" {
		t.Fatal("gateway should have rejected old version")
	}
	for i := 0; i < 10; i++ {
		g.mu.RLock()
		_, ok := g.peers[addr]
		g.mu.RUnlock()
		if ok {
			t.Fatal("gateway should not have added an old peer")
		}
		time.Sleep(20 * time.Millisecond)
	}

	// a simple 'conn.Close' would not obey the muxado disconnect protocol
	muxado.Client(conn).Close()

	// compliant connect with invalid port
	conn, err = net.Dial("tcp", string(g.Address()))
	if err != nil {
		t.Fatal("dial failed:", err)
	}
	addr = modules.NetAddress(conn.LocalAddr().String())
	ack, err = connectVersionHandshake(conn, build.Version)
	if err != nil {
		t.Fatal(err)
	}
	if ack != build.Version {
		t.Fatal("gateway should have given ack")
	}
	err = connectPortHandshake(conn, "0")
	if err != nil {
		t.Fatal(err)
	}
	for i := 0; i < 10; i++ {
		g.mu.RLock()
		_, ok := g.peers[addr]
		g.mu.RUnlock()
		if ok {
			t.Fatal("gateway should not have added a peer with an invalid port")
		}
		time.Sleep(20 * time.Millisecond)
	}

	// a simple 'conn.Close' would not obey the muxado disconnect protocol
	muxado.Client(conn).Close()

	// compliant connect
	conn, err = net.Dial("tcp", string(g.Address()))
	if err != nil {
		t.Fatal("dial failed:", err)
	}
	addr = modules.NetAddress(conn.LocalAddr().String())
	ack, err = connectVersionHandshake(conn, build.Version)
	if err != nil {
		t.Fatal(err)
	}
	if ack != build.Version {
		t.Fatal("gateway should have given ack")
	}
	err = connectPortHandshake(conn, addr.Port())
	if err != nil {
		t.Fatal(err)
	}

	// g should add the peer
	var ok bool
	for !ok {
		g.mu.RLock()
		_, ok = g.peers[addr]
		g.mu.RUnlock()
	}

	muxado.Client(conn).Close()

	// g should remove the peer
	for ok {
		g.mu.RLock()
		_, ok = g.peers[addr]
		g.mu.RUnlock()
	}

	// uncompliant connect
	conn, err = net.Dial("tcp", string(g.Address()))
	if err != nil {
		t.Fatal("dial failed:", err)
	}
	if _, err := conn.Write([]byte("missing length prefix")); err != nil {
		t.Fatal("couldn't write malformed header")
	}
	// g should have closed the connection
	if n, err := conn.Write([]byte("closed")); err != nil && n > 0 {
		t.Error("write succeeded after closed connection")
	}
}