1 | <?php |
||
12 | class Locator |
||
13 | { |
||
14 | |||
15 | /** |
||
16 | * @var Resolver |
||
17 | */ |
||
18 | private $dns; |
||
19 | |||
20 | /** |
||
21 | * @var NetworkAddressInterface[] |
||
22 | */ |
||
23 | private $knownAddresses = []; |
||
24 | |||
25 | /** |
||
26 | * @param Resolver $dns |
||
27 | */ |
||
28 | 6 | public function __construct(Resolver $dns) |
|
29 | { |
||
30 | 6 | $this->dns = $dns; |
|
31 | 6 | } |
|
32 | |||
33 | /** |
||
34 | * @param bool $randomize - return a randomized list of dns seeds |
||
35 | * @return string[] |
||
36 | */ |
||
37 | 6 | public static function dnsSeedHosts($randomize = true) |
|
38 | { |
||
39 | $seeds = [ |
||
40 | 6 | 'seed.bitcoin.sipa.be', |
|
41 | 4 | 'dnsseed.bluematt.me', |
|
42 | 4 | 'dnsseed.bitcoin.dashjr.org', |
|
43 | 4 | 'seed.bitcoinstats.com', |
|
44 | 4 | 'bitseed.xf2.org', |
|
45 | 4 | 'seed.bitnodes.io', |
|
46 | "seed.bitcoin.jonasschnelli.ch" |
||
47 | 4 | ]; |
|
48 | |||
49 | 6 | if ($randomize) { |
|
50 | 6 | shuffle($seeds); |
|
51 | 4 | } |
|
52 | |||
53 | 6 | return $seeds; |
|
54 | } |
||
55 | |||
56 | /** |
||
57 | * Connect to $numSeeds DNS seeds |
||
58 | * |
||
59 | * @param int $numSeeds |
||
60 | * @return \React\Promise\Promise|\React\Promise\PromiseInterface |
||
61 | */ |
||
62 | 3 | public function queryDnsSeeds($numSeeds = 1) |
|
63 | { |
||
64 | 3 | $peerList = new Deferred(); |
|
65 | |||
66 | // Take $numSeeds |
||
67 | 3 | $seedHosts = self::dnsSeedHosts(); |
|
68 | 3 | $seeds = array_slice($seedHosts, 0, min($numSeeds, count($seedHosts))); |
|
69 | |||
70 | // Connect to $numSeeds peers |
||
71 | /** @var Peer[] $vNetAddr */ |
||
72 | 3 | $vNetAddr = []; |
|
73 | 3 | foreach ($seeds as $seed) { |
|
74 | 3 | $this->dns |
|
75 | 3 | ->resolve($seed) |
|
76 | ->then(function ($ipList) use (&$vNetAddr, $peerList, &$numSeeds) { |
||
77 | 3 | $vNetAddr[] = $ipList; |
|
78 | 3 | if (count($vNetAddr) == $numSeeds) { |
|
79 | 3 | $peerList->resolve($vNetAddr); |
|
80 | 2 | } |
|
81 | 3 | }) |
|
82 | ; |
||
83 | 2 | } |
|
84 | |||
85 | // Compile the list of lists of peers into $this->knownAddresses |
||
86 | return $peerList |
||
87 | 3 | ->promise() |
|
88 | 3 | ->then( |
|
89 | function (array $vPeerVAddrs) { |
||
90 | 3 | shuffle($vPeerVAddrs); |
|
91 | |||
92 | /** @var NetworkAddressInterface[] $addresses */ |
||
93 | 3 | $addresses = []; |
|
94 | 3 | array_map( |
|
95 | 3 | function (array $value) use (&$addresses) { |
|
96 | 3 | foreach ($value as $ip) { |
|
97 | 3 | $addresses[] = new NetworkAddress( |
|
98 | 3 | Services::NETWORK, |
|
99 | 3 | new Ipv4($ip), |
|
100 | 1 | 8333 |
|
101 | 2 | ); |
|
102 | 2 | } |
|
103 | 3 | }, |
|
104 | $vPeerVAddrs |
||
105 | 2 | ); |
|
106 | |||
107 | 3 | $this->knownAddresses = array_merge( |
|
108 | 3 | $this->knownAddresses, |
|
109 | $addresses |
||
110 | 2 | ); |
|
111 | |||
112 | 3 | return $this; |
|
113 | 1 | } |
|
114 | 2 | ) |
|
115 | 2 | ; |
|
116 | } |
||
117 | |||
118 | /** |
||
119 | * @return NetworkAddressInterface[] |
||
120 | */ |
||
121 | 3 | public function getKnownAddresses() |
|
125 | |||
126 | /** |
||
127 | * Pop an address from the discovered peers |
||
128 | * |
||
129 | * @return NetworkAddressInterface |
||
130 | * @throws \Exception |
||
131 | */ |
||
132 | 3 | public function popAddress() |
|
140 | } |
||
141 |