dial_test.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package p2p
  17. import (
  18. "encoding/binary"
  19. "net"
  20. "reflect"
  21. "testing"
  22. "time"
  23. "github.com/davecgh/go-spew/spew"
  24. "github.com/ethereum/go-ethereum/p2p/enode"
  25. "github.com/ethereum/go-ethereum/p2p/enr"
  26. "github.com/ethereum/go-ethereum/p2p/netutil"
  27. )
  28. func init() {
  29. spew.Config.Indent = "\t"
  30. }
  31. type dialtest struct {
  32. init *dialstate // state before and after the test.
  33. rounds []round
  34. }
  35. type round struct {
  36. peers []*Peer // current peer set
  37. done []task // tasks that got done this round
  38. new []task // the result must match this one
  39. }
  40. func runDialTest(t *testing.T, test dialtest) {
  41. var (
  42. vtime time.Time
  43. running int
  44. )
  45. pm := func(ps []*Peer) map[enode.ID]*Peer {
  46. m := make(map[enode.ID]*Peer)
  47. for _, p := range ps {
  48. m[p.ID()] = p
  49. }
  50. return m
  51. }
  52. for i, round := range test.rounds {
  53. for _, task := range round.done {
  54. running--
  55. if running < 0 {
  56. panic("running task counter underflow")
  57. }
  58. test.init.taskDone(task, vtime)
  59. }
  60. new := test.init.newTasks(running, pm(round.peers), vtime)
  61. if !sametasks(new, round.new) {
  62. t.Errorf("round %d: new tasks mismatch:\ngot %v\nwant %v\nstate: %v\nrunning: %v\n",
  63. i, spew.Sdump(new), spew.Sdump(round.new), spew.Sdump(test.init), spew.Sdump(running))
  64. }
  65. t.Log("tasks:", spew.Sdump(new))
  66. // Time advances by 16 seconds on every round.
  67. vtime = vtime.Add(16 * time.Second)
  68. running += len(new)
  69. }
  70. }
  71. type fakeTable []*enode.Node
  72. func (t fakeTable) Self() *enode.Node { return new(enode.Node) }
  73. func (t fakeTable) Close() {}
  74. func (t fakeTable) LookupRandom() []*enode.Node { return nil }
  75. func (t fakeTable) Resolve(*enode.Node) *enode.Node { return nil }
  76. func (t fakeTable) ReadRandomNodes(buf []*enode.Node) int { return copy(buf, t) }
  77. // This test checks that dynamic dials are launched from discovery results.
  78. func TestDialStateDynDial(t *testing.T) {
  79. runDialTest(t, dialtest{
  80. init: newDialState(enode.ID{}, nil, nil, fakeTable{}, 5, nil),
  81. rounds: []round{
  82. // A discovery query is launched.
  83. {
  84. peers: []*Peer{
  85. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
  86. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  87. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  88. },
  89. new: []task{&discoverTask{}},
  90. },
  91. // Dynamic dials are launched when it completes.
  92. {
  93. peers: []*Peer{
  94. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
  95. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  96. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  97. },
  98. done: []task{
  99. &discoverTask{results: []*enode.Node{
  100. newNode(uintID(2), nil), // this one is already connected and not dialed.
  101. newNode(uintID(3), nil),
  102. newNode(uintID(4), nil),
  103. newNode(uintID(5), nil),
  104. newNode(uintID(6), nil), // these are not tried because max dyn dials is 5
  105. newNode(uintID(7), nil), // ...
  106. }},
  107. },
  108. new: []task{
  109. &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
  110. &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
  111. &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
  112. },
  113. },
  114. // Some of the dials complete but no new ones are launched yet because
  115. // the sum of active dial count and dynamic peer count is == maxDynDials.
  116. {
  117. peers: []*Peer{
  118. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
  119. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  120. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  121. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
  122. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
  123. },
  124. done: []task{
  125. &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
  126. &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
  127. },
  128. },
  129. // No new dial tasks are launched in the this round because
  130. // maxDynDials has been reached.
  131. {
  132. peers: []*Peer{
  133. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
  134. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  135. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  136. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
  137. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
  138. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
  139. },
  140. done: []task{
  141. &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
  142. },
  143. new: []task{
  144. &waitExpireTask{Duration: 14 * time.Second},
  145. },
  146. },
  147. // In this round, the peer with id 2 drops off. The query
  148. // results from last discovery lookup are reused.
  149. {
  150. peers: []*Peer{
  151. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
  152. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  153. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
  154. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
  155. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
  156. },
  157. new: []task{
  158. &dialTask{flags: dynDialedConn, dest: newNode(uintID(6), nil)},
  159. },
  160. },
  161. // More peers (3,4) drop off and dial for ID 6 completes.
  162. // The last query result from the discovery lookup is reused
  163. // and a new one is spawned because more candidates are needed.
  164. {
  165. peers: []*Peer{
  166. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
  167. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  168. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
  169. },
  170. done: []task{
  171. &dialTask{flags: dynDialedConn, dest: newNode(uintID(6), nil)},
  172. },
  173. new: []task{
  174. &dialTask{flags: dynDialedConn, dest: newNode(uintID(7), nil)},
  175. &discoverTask{},
  176. },
  177. },
  178. // Peer 7 is connected, but there still aren't enough dynamic peers
  179. // (4 out of 5). However, a discovery is already running, so ensure
  180. // no new is started.
  181. {
  182. peers: []*Peer{
  183. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
  184. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  185. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
  186. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(7), nil)}},
  187. },
  188. done: []task{
  189. &dialTask{flags: dynDialedConn, dest: newNode(uintID(7), nil)},
  190. },
  191. },
  192. // Finish the running node discovery with an empty set. A new lookup
  193. // should be immediately requested.
  194. {
  195. peers: []*Peer{
  196. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
  197. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  198. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
  199. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(7), nil)}},
  200. },
  201. done: []task{
  202. &discoverTask{},
  203. },
  204. new: []task{
  205. &discoverTask{},
  206. },
  207. },
  208. },
  209. })
  210. }
  211. // Tests that bootnodes are dialed if no peers are connectd, but not otherwise.
  212. func TestDialStateDynDialBootnode(t *testing.T) {
  213. bootnodes := []*enode.Node{
  214. newNode(uintID(1), nil),
  215. newNode(uintID(2), nil),
  216. newNode(uintID(3), nil),
  217. }
  218. table := fakeTable{
  219. newNode(uintID(4), nil),
  220. newNode(uintID(5), nil),
  221. newNode(uintID(6), nil),
  222. newNode(uintID(7), nil),
  223. newNode(uintID(8), nil),
  224. }
  225. runDialTest(t, dialtest{
  226. init: newDialState(enode.ID{}, nil, bootnodes, table, 5, nil),
  227. rounds: []round{
  228. // 2 dynamic dials attempted, bootnodes pending fallback interval
  229. {
  230. new: []task{
  231. &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
  232. &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
  233. &discoverTask{},
  234. },
  235. },
  236. // No dials succeed, bootnodes still pending fallback interval
  237. {
  238. done: []task{
  239. &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
  240. &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
  241. },
  242. },
  243. // No dials succeed, bootnodes still pending fallback interval
  244. {},
  245. // No dials succeed, 2 dynamic dials attempted and 1 bootnode too as fallback interval was reached
  246. {
  247. new: []task{
  248. &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
  249. &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
  250. &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
  251. },
  252. },
  253. // No dials succeed, 2nd bootnode is attempted
  254. {
  255. done: []task{
  256. &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
  257. &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
  258. &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
  259. },
  260. new: []task{
  261. &dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
  262. },
  263. },
  264. // No dials succeed, 3rd bootnode is attempted
  265. {
  266. done: []task{
  267. &dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
  268. },
  269. new: []task{
  270. &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
  271. },
  272. },
  273. // No dials succeed, 1st bootnode is attempted again, expired random nodes retried
  274. {
  275. done: []task{
  276. &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
  277. },
  278. new: []task{
  279. &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
  280. &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
  281. &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
  282. },
  283. },
  284. // Random dial succeeds, no more bootnodes are attempted
  285. {
  286. peers: []*Peer{
  287. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
  288. },
  289. done: []task{
  290. &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
  291. &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
  292. &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
  293. },
  294. },
  295. },
  296. })
  297. }
  298. func TestDialStateDynDialFromTable(t *testing.T) {
  299. // This table always returns the same random nodes
  300. // in the order given below.
  301. table := fakeTable{
  302. newNode(uintID(1), nil),
  303. newNode(uintID(2), nil),
  304. newNode(uintID(3), nil),
  305. newNode(uintID(4), nil),
  306. newNode(uintID(5), nil),
  307. newNode(uintID(6), nil),
  308. newNode(uintID(7), nil),
  309. newNode(uintID(8), nil),
  310. }
  311. runDialTest(t, dialtest{
  312. init: newDialState(enode.ID{}, nil, nil, table, 10, nil),
  313. rounds: []round{
  314. // 5 out of 8 of the nodes returned by ReadRandomNodes are dialed.
  315. {
  316. new: []task{
  317. &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
  318. &dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
  319. &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
  320. &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
  321. &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
  322. &discoverTask{},
  323. },
  324. },
  325. // Dialing nodes 1,2 succeeds. Dials from the lookup are launched.
  326. {
  327. peers: []*Peer{
  328. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  329. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  330. },
  331. done: []task{
  332. &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
  333. &dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
  334. &discoverTask{results: []*enode.Node{
  335. newNode(uintID(10), nil),
  336. newNode(uintID(11), nil),
  337. newNode(uintID(12), nil),
  338. }},
  339. },
  340. new: []task{
  341. &dialTask{flags: dynDialedConn, dest: newNode(uintID(10), nil)},
  342. &dialTask{flags: dynDialedConn, dest: newNode(uintID(11), nil)},
  343. &dialTask{flags: dynDialedConn, dest: newNode(uintID(12), nil)},
  344. &discoverTask{},
  345. },
  346. },
  347. // Dialing nodes 3,4,5 fails. The dials from the lookup succeed.
  348. {
  349. peers: []*Peer{
  350. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  351. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  352. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
  353. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
  354. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
  355. },
  356. done: []task{
  357. &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
  358. &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
  359. &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
  360. &dialTask{flags: dynDialedConn, dest: newNode(uintID(10), nil)},
  361. &dialTask{flags: dynDialedConn, dest: newNode(uintID(11), nil)},
  362. &dialTask{flags: dynDialedConn, dest: newNode(uintID(12), nil)},
  363. },
  364. },
  365. // Waiting for expiry. No waitExpireTask is launched because the
  366. // discovery query is still running.
  367. {
  368. peers: []*Peer{
  369. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  370. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  371. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
  372. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
  373. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
  374. },
  375. },
  376. // Nodes 3,4 are not tried again because only the first two
  377. // returned random nodes (nodes 1,2) are tried and they're
  378. // already connected.
  379. {
  380. peers: []*Peer{
  381. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  382. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  383. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
  384. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
  385. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
  386. },
  387. },
  388. },
  389. })
  390. }
  391. func newNode(id enode.ID, ip net.IP) *enode.Node {
  392. var r enr.Record
  393. if ip != nil {
  394. r.Set(enr.IP(ip))
  395. }
  396. return enode.SignNull(&r, id)
  397. }
  398. // This test checks that candidates that do not match the netrestrict list are not dialed.
  399. func TestDialStateNetRestrict(t *testing.T) {
  400. // This table always returns the same random nodes
  401. // in the order given below.
  402. table := fakeTable{
  403. newNode(uintID(1), net.ParseIP("127.0.0.1")),
  404. newNode(uintID(2), net.ParseIP("127.0.0.2")),
  405. newNode(uintID(3), net.ParseIP("127.0.0.3")),
  406. newNode(uintID(4), net.ParseIP("127.0.0.4")),
  407. newNode(uintID(5), net.ParseIP("127.0.2.5")),
  408. newNode(uintID(6), net.ParseIP("127.0.2.6")),
  409. newNode(uintID(7), net.ParseIP("127.0.2.7")),
  410. newNode(uintID(8), net.ParseIP("127.0.2.8")),
  411. }
  412. restrict := new(netutil.Netlist)
  413. restrict.Add("127.0.2.0/24")
  414. runDialTest(t, dialtest{
  415. init: newDialState(enode.ID{}, nil, nil, table, 10, restrict),
  416. rounds: []round{
  417. {
  418. new: []task{
  419. &dialTask{flags: dynDialedConn, dest: table[4]},
  420. &discoverTask{},
  421. },
  422. },
  423. },
  424. })
  425. }
  426. // This test checks that static dials are launched.
  427. func TestDialStateStaticDial(t *testing.T) {
  428. wantStatic := []*enode.Node{
  429. newNode(uintID(1), nil),
  430. newNode(uintID(2), nil),
  431. newNode(uintID(3), nil),
  432. newNode(uintID(4), nil),
  433. newNode(uintID(5), nil),
  434. }
  435. runDialTest(t, dialtest{
  436. init: newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil),
  437. rounds: []round{
  438. // Static dials are launched for the nodes that
  439. // aren't yet connected.
  440. {
  441. peers: []*Peer{
  442. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  443. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  444. },
  445. new: []task{
  446. &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
  447. &dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)},
  448. &dialTask{flags: staticDialedConn, dest: newNode(uintID(5), nil)},
  449. },
  450. },
  451. // No new tasks are launched in this round because all static
  452. // nodes are either connected or still being dialed.
  453. {
  454. peers: []*Peer{
  455. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  456. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  457. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
  458. },
  459. done: []task{
  460. &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
  461. },
  462. },
  463. // No new dial tasks are launched because all static
  464. // nodes are now connected.
  465. {
  466. peers: []*Peer{
  467. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  468. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  469. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
  470. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(4), nil)}},
  471. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}},
  472. },
  473. done: []task{
  474. &dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)},
  475. &dialTask{flags: staticDialedConn, dest: newNode(uintID(5), nil)},
  476. },
  477. new: []task{
  478. &waitExpireTask{Duration: 14 * time.Second},
  479. },
  480. },
  481. // Wait a round for dial history to expire, no new tasks should spawn.
  482. {
  483. peers: []*Peer{
  484. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  485. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  486. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
  487. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(4), nil)}},
  488. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}},
  489. },
  490. },
  491. // If a static node is dropped, it should be immediately redialed,
  492. // irrespective whether it was originally static or dynamic.
  493. {
  494. peers: []*Peer{
  495. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  496. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
  497. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}},
  498. },
  499. new: []task{
  500. &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
  501. &dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)},
  502. },
  503. },
  504. },
  505. })
  506. }
  507. // This test checks that static peers will be redialed immediately if they were re-added to a static list.
  508. func TestDialStaticAfterReset(t *testing.T) {
  509. wantStatic := []*enode.Node{
  510. newNode(uintID(1), nil),
  511. newNode(uintID(2), nil),
  512. }
  513. rounds := []round{
  514. // Static dials are launched for the nodes that aren't yet connected.
  515. {
  516. peers: nil,
  517. new: []task{
  518. &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
  519. &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
  520. },
  521. },
  522. // No new dial tasks, all peers are connected.
  523. {
  524. peers: []*Peer{
  525. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(1), nil)}},
  526. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(2), nil)}},
  527. },
  528. done: []task{
  529. &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
  530. &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
  531. },
  532. new: []task{
  533. &waitExpireTask{Duration: 30 * time.Second},
  534. },
  535. },
  536. }
  537. dTest := dialtest{
  538. init: newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil),
  539. rounds: rounds,
  540. }
  541. runDialTest(t, dTest)
  542. for _, n := range wantStatic {
  543. dTest.init.removeStatic(n)
  544. dTest.init.addStatic(n)
  545. }
  546. // without removing peers they will be considered recently dialed
  547. runDialTest(t, dTest)
  548. }
  549. // This test checks that past dials are not retried for some time.
  550. func TestDialStateCache(t *testing.T) {
  551. wantStatic := []*enode.Node{
  552. newNode(uintID(1), nil),
  553. newNode(uintID(2), nil),
  554. newNode(uintID(3), nil),
  555. }
  556. runDialTest(t, dialtest{
  557. init: newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil),
  558. rounds: []round{
  559. // Static dials are launched for the nodes that
  560. // aren't yet connected.
  561. {
  562. peers: nil,
  563. new: []task{
  564. &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
  565. &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
  566. &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
  567. },
  568. },
  569. // No new tasks are launched in this round because all static
  570. // nodes are either connected or still being dialed.
  571. {
  572. peers: []*Peer{
  573. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(1), nil)}},
  574. {rw: &conn{flags: staticDialedConn, node: newNode(uintID(2), nil)}},
  575. },
  576. done: []task{
  577. &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
  578. &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
  579. },
  580. },
  581. // A salvage task is launched to wait for node 3's history
  582. // entry to expire.
  583. {
  584. peers: []*Peer{
  585. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  586. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  587. },
  588. done: []task{
  589. &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
  590. },
  591. new: []task{
  592. &waitExpireTask{Duration: 14 * time.Second},
  593. },
  594. },
  595. // Still waiting for node 3's entry to expire in the cache.
  596. {
  597. peers: []*Peer{
  598. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  599. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  600. },
  601. },
  602. // The cache entry for node 3 has expired and is retried.
  603. {
  604. peers: []*Peer{
  605. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
  606. {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
  607. },
  608. new: []task{
  609. &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
  610. },
  611. },
  612. },
  613. })
  614. }
  615. func TestDialResolve(t *testing.T) {
  616. resolved := newNode(uintID(1), net.IP{127, 0, 55, 234})
  617. table := &resolveMock{answer: resolved}
  618. state := newDialState(enode.ID{}, nil, nil, table, 0, nil)
  619. // Check that the task is generated with an incomplete ID.
  620. dest := newNode(uintID(1), nil)
  621. state.addStatic(dest)
  622. tasks := state.newTasks(0, nil, time.Time{})
  623. if !reflect.DeepEqual(tasks, []task{&dialTask{flags: staticDialedConn, dest: dest}}) {
  624. t.Fatalf("expected dial task, got %#v", tasks)
  625. }
  626. // Now run the task, it should resolve the ID once.
  627. config := Config{Dialer: TCPDialer{&net.Dialer{Deadline: time.Now().Add(-5 * time.Minute)}}}
  628. srv := &Server{ntab: table, Config: config}
  629. tasks[0].Do(srv)
  630. if !reflect.DeepEqual(table.resolveCalls, []*enode.Node{dest}) {
  631. t.Fatalf("wrong resolve calls, got %v", table.resolveCalls)
  632. }
  633. // Report it as done to the dialer, which should update the static node record.
  634. state.taskDone(tasks[0], time.Now())
  635. if state.static[uintID(1)].dest != resolved {
  636. t.Fatalf("state.dest not updated")
  637. }
  638. }
  639. // compares task lists but doesn't care about the order.
  640. func sametasks(a, b []task) bool {
  641. if len(a) != len(b) {
  642. return false
  643. }
  644. next:
  645. for _, ta := range a {
  646. for _, tb := range b {
  647. if reflect.DeepEqual(ta, tb) {
  648. continue next
  649. }
  650. }
  651. return false
  652. }
  653. return true
  654. }
  655. func uintID(i uint32) enode.ID {
  656. var id enode.ID
  657. binary.BigEndian.PutUint32(id[:], i)
  658. return id
  659. }
  660. // implements discoverTable for TestDialResolve
  661. type resolveMock struct {
  662. resolveCalls []*enode.Node
  663. answer *enode.Node
  664. }
  665. func (t *resolveMock) Resolve(n *enode.Node) *enode.Node {
  666. t.resolveCalls = append(t.resolveCalls, n)
  667. return t.answer
  668. }
  669. func (t *resolveMock) Self() *enode.Node { return new(enode.Node) }
  670. func (t *resolveMock) Close() {}
  671. func (t *resolveMock) LookupRandom() []*enode.Node { return nil }
  672. func (t *resolveMock) ReadRandomNodes(buf []*enode.Node) int { return 0 }