dial_test.go 23 KB

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