p2p: if no nodes are connected, attempt dialing bootnodes (#13874)

This commit is contained in:
Péter Szilágyi
2017-04-10 19:33:41 +03:00
committed by Felix Lange
parent 542e42b21e
commit 04fcae207d
3 changed files with 120 additions and 8 deletions

View File

@ -87,7 +87,7 @@ func (t fakeTable) ReadRandomNodes(buf []*discover.Node) int { return copy(buf,
// This test checks that dynamic dials are launched from discovery results.
func TestDialStateDynDial(t *testing.T) {
runDialTest(t, dialtest{
init: newDialState(nil, fakeTable{}, 5, nil),
init: newDialState(nil, nil, fakeTable{}, 5, nil),
rounds: []round{
// A discovery query is launched.
{
@ -219,6 +219,94 @@ func TestDialStateDynDial(t *testing.T) {
})
}
// Tests that bootnodes are dialed if no peers are connectd, but not otherwise.
func TestDialStateDynDialBootnode(t *testing.T) {
bootnodes := []*discover.Node{
{ID: uintID(1)},
{ID: uintID(2)},
{ID: uintID(3)},
}
table := fakeTable{
{ID: uintID(4)},
{ID: uintID(5)},
{ID: uintID(6)},
{ID: uintID(7)},
{ID: uintID(8)},
}
runDialTest(t, dialtest{
init: newDialState(nil, bootnodes, table, 5, nil),
rounds: []round{
// 2 dynamic dials attempted, bootnodes pending fallback interval
{
new: []task{
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}},
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}},
&discoverTask{},
},
},
// No dials succeed, bootnodes still pending fallback interval
{
done: []task{
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}},
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}},
},
},
// No dials succeed, bootnodes still pending fallback interval
{},
// No dials succeed, 2 dynamic dials attempted and 1 bootnode too as fallback interval was reached
{
new: []task{
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}},
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}},
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}},
},
},
// No dials succeed, 2nd bootnode is attempted
{
done: []task{
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}},
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}},
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}},
},
new: []task{
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(2)}},
},
},
// No dials succeed, 3rd bootnode is attempted
{
done: []task{
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(2)}},
},
new: []task{
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}},
},
},
// No dials succeed, 1st bootnode is attempted again, expired random nodes retried
{
done: []task{
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}},
},
new: []task{
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}},
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}},
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}},
},
},
// Random dial succeeds, no more bootnodes are attempted
{
peers: []*Peer{
{rw: &conn{flags: dynDialedConn, id: uintID(4)}},
},
done: []task{
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}},
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}},
&dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}},
},
},
},
})
}
func TestDialStateDynDialFromTable(t *testing.T) {
// This table always returns the same random nodes
// in the order given below.
@ -234,7 +322,7 @@ func TestDialStateDynDialFromTable(t *testing.T) {
}
runDialTest(t, dialtest{
init: newDialState(nil, table, 10, nil),
init: newDialState(nil, nil, table, 10, nil),
rounds: []round{
// 5 out of 8 of the nodes returned by ReadRandomNodes are dialed.
{
@ -332,7 +420,7 @@ func TestDialStateNetRestrict(t *testing.T) {
restrict.Add("127.0.2.0/24")
runDialTest(t, dialtest{
init: newDialState(nil, table, 10, restrict),
init: newDialState(nil, nil, table, 10, restrict),
rounds: []round{
{
new: []task{
@ -355,7 +443,7 @@ func TestDialStateStaticDial(t *testing.T) {
}
runDialTest(t, dialtest{
init: newDialState(wantStatic, fakeTable{}, 0, nil),
init: newDialState(wantStatic, nil, fakeTable{}, 0, nil),
rounds: []round{
// Static dials are launched for the nodes that
// aren't yet connected.
@ -436,7 +524,7 @@ func TestDialStateCache(t *testing.T) {
}
runDialTest(t, dialtest{
init: newDialState(wantStatic, fakeTable{}, 0, nil),
init: newDialState(wantStatic, nil, fakeTable{}, 0, nil),
rounds: []round{
// Static dials are launched for the nodes that
// aren't yet connected.
@ -498,7 +586,7 @@ func TestDialStateCache(t *testing.T) {
func TestDialResolve(t *testing.T) {
resolved := discover.NewNode(uintID(1), net.IP{127, 0, 55, 234}, 3333, 4444)
table := &resolveMock{answer: resolved}
state := newDialState(nil, table, 0, nil)
state := newDialState(nil, nil, table, 0, nil)
// Check that the task is generated with an incomplete ID.
dest := discover.NewNode(uintID(1), nil, 0, 0)