Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
04fcae20
Commit
04fcae20
authored
Apr 10, 2017
by
Péter Szilágyi
Committed by
Felix Lange
Apr 10, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
p2p: if no nodes are connected, attempt dialing bootnodes (#13874)
parent
542e42b2
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
121 additions
and
9 deletions
+121
-9
dial.go
p2p/dial.go
+26
-2
dial_test.go
p2p/dial_test.go
+94
-6
server.go
p2p/server.go
+1
-1
No files found.
p2p/dial.go
View file @
04fcae20
...
@@ -38,6 +38,10 @@ const (
...
@@ -38,6 +38,10 @@ const (
// once every few seconds.
// once every few seconds.
lookupInterval
=
4
*
time
.
Second
lookupInterval
=
4
*
time
.
Second
// If no peers are found for this amount of time, the initial bootnodes are
// attempted to be connected.
fallbackInterval
=
20
*
time
.
Second
// Endpoint resolution is throttled with bounded backoff.
// Endpoint resolution is throttled with bounded backoff.
initialResolveDelay
=
60
*
time
.
Second
initialResolveDelay
=
60
*
time
.
Second
maxResolveDelay
=
time
.
Hour
maxResolveDelay
=
time
.
Hour
...
@@ -57,6 +61,9 @@ type dialstate struct {
...
@@ -57,6 +61,9 @@ type dialstate struct {
randomNodes
[]
*
discover
.
Node
// filled from Table
randomNodes
[]
*
discover
.
Node
// filled from Table
static
map
[
discover
.
NodeID
]
*
dialTask
static
map
[
discover
.
NodeID
]
*
dialTask
hist
*
dialHistory
hist
*
dialHistory
start
time
.
Time
// time when the dialer was first used
bootnodes
[]
*
discover
.
Node
// default dials when there are no peers
}
}
type
discoverTable
interface
{
type
discoverTable
interface
{
...
@@ -102,16 +109,18 @@ type waitExpireTask struct {
...
@@ -102,16 +109,18 @@ type waitExpireTask struct {
time
.
Duration
time
.
Duration
}
}
func
newDialState
(
static
[]
*
discover
.
Node
,
ntab
discoverTable
,
maxdyn
int
,
netrestrict
*
netutil
.
Netlist
)
*
dialstate
{
func
newDialState
(
static
[]
*
discover
.
Node
,
bootnodes
[]
*
discover
.
Node
,
ntab
discoverTable
,
maxdyn
int
,
netrestrict
*
netutil
.
Netlist
)
*
dialstate
{
s
:=
&
dialstate
{
s
:=
&
dialstate
{
maxDynDials
:
maxdyn
,
maxDynDials
:
maxdyn
,
ntab
:
ntab
,
ntab
:
ntab
,
netrestrict
:
netrestrict
,
netrestrict
:
netrestrict
,
static
:
make
(
map
[
discover
.
NodeID
]
*
dialTask
),
static
:
make
(
map
[
discover
.
NodeID
]
*
dialTask
),
dialing
:
make
(
map
[
discover
.
NodeID
]
connFlag
),
dialing
:
make
(
map
[
discover
.
NodeID
]
connFlag
),
bootnodes
:
make
([]
*
discover
.
Node
,
len
(
bootnodes
)),
randomNodes
:
make
([]
*
discover
.
Node
,
maxdyn
/
2
),
randomNodes
:
make
([]
*
discover
.
Node
,
maxdyn
/
2
),
hist
:
new
(
dialHistory
),
hist
:
new
(
dialHistory
),
}
}
copy
(
s
.
bootnodes
,
bootnodes
)
for
_
,
n
:=
range
static
{
for
_
,
n
:=
range
static
{
s
.
addStatic
(
n
)
s
.
addStatic
(
n
)
}
}
...
@@ -130,6 +139,10 @@ func (s *dialstate) removeStatic(n *discover.Node) {
...
@@ -130,6 +139,10 @@ func (s *dialstate) removeStatic(n *discover.Node) {
}
}
func
(
s
*
dialstate
)
newTasks
(
nRunning
int
,
peers
map
[
discover
.
NodeID
]
*
Peer
,
now
time
.
Time
)
[]
task
{
func
(
s
*
dialstate
)
newTasks
(
nRunning
int
,
peers
map
[
discover
.
NodeID
]
*
Peer
,
now
time
.
Time
)
[]
task
{
if
s
.
start
==
(
time
.
Time
{})
{
s
.
start
=
now
}
var
newtasks
[]
task
var
newtasks
[]
task
addDial
:=
func
(
flag
connFlag
,
n
*
discover
.
Node
)
bool
{
addDial
:=
func
(
flag
connFlag
,
n
*
discover
.
Node
)
bool
{
if
err
:=
s
.
checkDial
(
n
,
peers
);
err
!=
nil
{
if
err
:=
s
.
checkDial
(
n
,
peers
);
err
!=
nil
{
...
@@ -169,7 +182,18 @@ func (s *dialstate) newTasks(nRunning int, peers map[discover.NodeID]*Peer, now
...
@@ -169,7 +182,18 @@ func (s *dialstate) newTasks(nRunning int, peers map[discover.NodeID]*Peer, now
newtasks
=
append
(
newtasks
,
t
)
newtasks
=
append
(
newtasks
,
t
)
}
}
}
}
// If we don't have any peers whatsoever, try to dial a random bootnode. This
// scenario is useful for the testnet (and private networks) where the discovery
// table might be full of mostly bad peers, making it hard to find good ones.
if
len
(
peers
)
==
0
&&
len
(
s
.
bootnodes
)
>
0
&&
needDynDials
>
0
&&
now
.
Sub
(
s
.
start
)
>
fallbackInterval
{
bootnode
:=
s
.
bootnodes
[
0
]
s
.
bootnodes
=
append
(
s
.
bootnodes
[
:
0
],
s
.
bootnodes
[
1
:
]
...
)
s
.
bootnodes
=
append
(
s
.
bootnodes
,
bootnode
)
if
addDial
(
dynDialedConn
,
bootnode
)
{
needDynDials
--
}
}
// Use random nodes from the table for half of the necessary
// Use random nodes from the table for half of the necessary
// dynamic dials.
// dynamic dials.
randomCandidates
:=
needDynDials
/
2
randomCandidates
:=
needDynDials
/
2
...
...
p2p/dial_test.go
View file @
04fcae20
...
@@ -87,7 +87,7 @@ func (t fakeTable) ReadRandomNodes(buf []*discover.Node) int { return copy(buf,
...
@@ -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.
// This test checks that dynamic dials are launched from discovery results.
func
TestDialStateDynDial
(
t
*
testing
.
T
)
{
func
TestDialStateDynDial
(
t
*
testing
.
T
)
{
runDialTest
(
t
,
dialtest
{
runDialTest
(
t
,
dialtest
{
init
:
newDialState
(
nil
,
fakeTable
{},
5
,
nil
),
init
:
newDialState
(
nil
,
nil
,
fakeTable
{},
5
,
nil
),
rounds
:
[]
round
{
rounds
:
[]
round
{
// A discovery query is launched.
// A discovery query is launched.
{
{
...
@@ -219,6 +219,94 @@ func TestDialStateDynDial(t *testing.T) {
...
@@ -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
)
{
func
TestDialStateDynDialFromTable
(
t
*
testing
.
T
)
{
// This table always returns the same random nodes
// This table always returns the same random nodes
// in the order given below.
// in the order given below.
...
@@ -234,7 +322,7 @@ func TestDialStateDynDialFromTable(t *testing.T) {
...
@@ -234,7 +322,7 @@ func TestDialStateDynDialFromTable(t *testing.T) {
}
}
runDialTest
(
t
,
dialtest
{
runDialTest
(
t
,
dialtest
{
init
:
newDialState
(
nil
,
table
,
10
,
nil
),
init
:
newDialState
(
nil
,
nil
,
table
,
10
,
nil
),
rounds
:
[]
round
{
rounds
:
[]
round
{
// 5 out of 8 of the nodes returned by ReadRandomNodes are dialed.
// 5 out of 8 of the nodes returned by ReadRandomNodes are dialed.
{
{
...
@@ -332,7 +420,7 @@ func TestDialStateNetRestrict(t *testing.T) {
...
@@ -332,7 +420,7 @@ func TestDialStateNetRestrict(t *testing.T) {
restrict
.
Add
(
"127.0.2.0/24"
)
restrict
.
Add
(
"127.0.2.0/24"
)
runDialTest
(
t
,
dialtest
{
runDialTest
(
t
,
dialtest
{
init
:
newDialState
(
nil
,
table
,
10
,
restrict
),
init
:
newDialState
(
nil
,
nil
,
table
,
10
,
restrict
),
rounds
:
[]
round
{
rounds
:
[]
round
{
{
{
new
:
[]
task
{
new
:
[]
task
{
...
@@ -355,7 +443,7 @@ func TestDialStateStaticDial(t *testing.T) {
...
@@ -355,7 +443,7 @@ func TestDialStateStaticDial(t *testing.T) {
}
}
runDialTest
(
t
,
dialtest
{
runDialTest
(
t
,
dialtest
{
init
:
newDialState
(
wantStatic
,
fakeTable
{},
0
,
nil
),
init
:
newDialState
(
wantStatic
,
nil
,
fakeTable
{},
0
,
nil
),
rounds
:
[]
round
{
rounds
:
[]
round
{
// Static dials are launched for the nodes that
// Static dials are launched for the nodes that
// aren't yet connected.
// aren't yet connected.
...
@@ -436,7 +524,7 @@ func TestDialStateCache(t *testing.T) {
...
@@ -436,7 +524,7 @@ func TestDialStateCache(t *testing.T) {
}
}
runDialTest
(
t
,
dialtest
{
runDialTest
(
t
,
dialtest
{
init
:
newDialState
(
wantStatic
,
fakeTable
{},
0
,
nil
),
init
:
newDialState
(
wantStatic
,
nil
,
fakeTable
{},
0
,
nil
),
rounds
:
[]
round
{
rounds
:
[]
round
{
// Static dials are launched for the nodes that
// Static dials are launched for the nodes that
// aren't yet connected.
// aren't yet connected.
...
@@ -498,7 +586,7 @@ func TestDialStateCache(t *testing.T) {
...
@@ -498,7 +586,7 @@ func TestDialStateCache(t *testing.T) {
func
TestDialResolve
(
t
*
testing
.
T
)
{
func
TestDialResolve
(
t
*
testing
.
T
)
{
resolved
:=
discover
.
NewNode
(
uintID
(
1
),
net
.
IP
{
127
,
0
,
55
,
234
},
3333
,
4444
)
resolved
:=
discover
.
NewNode
(
uintID
(
1
),
net
.
IP
{
127
,
0
,
55
,
234
},
3333
,
4444
)
table
:=
&
resolveMock
{
answer
:
resolved
}
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.
// Check that the task is generated with an incomplete ID.
dest
:=
discover
.
NewNode
(
uintID
(
1
),
nil
,
0
,
0
)
dest
:=
discover
.
NewNode
(
uintID
(
1
),
nil
,
0
,
0
)
...
...
p2p/server.go
View file @
04fcae20
...
@@ -396,7 +396,7 @@ func (srv *Server) Start() (err error) {
...
@@ -396,7 +396,7 @@ func (srv *Server) Start() (err error) {
if
!
srv
.
Discovery
{
if
!
srv
.
Discovery
{
dynPeers
=
0
dynPeers
=
0
}
}
dialer
:=
newDialState
(
srv
.
StaticNodes
,
srv
.
ntab
,
dynPeers
,
srv
.
NetRestrict
)
dialer
:=
newDialState
(
srv
.
StaticNodes
,
srv
.
BootstrapNodes
,
srv
.
ntab
,
dynPeers
,
srv
.
NetRestrict
)
// handshake
// handshake
srv
.
ourHandshake
=
&
protoHandshake
{
Version
:
baseProtocolVersion
,
Name
:
srv
.
Name
,
ID
:
discover
.
PubkeyID
(
&
srv
.
PrivateKey
.
PublicKey
)}
srv
.
ourHandshake
=
&
protoHandshake
{
Version
:
baseProtocolVersion
,
Name
:
srv
.
Name
,
ID
:
discover
.
PubkeyID
(
&
srv
.
PrivateKey
.
PublicKey
)}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment