1 | <?php |
||
11 | class Manager extends EventEmitter |
||
12 | { |
||
13 | /** |
||
14 | * @var Connector |
||
15 | */ |
||
16 | private $connector; |
||
17 | |||
18 | /** |
||
19 | * @var Peer[] |
||
20 | */ |
||
21 | private $outPeers = []; |
||
22 | |||
23 | /** |
||
24 | * @var Peer[] |
||
25 | */ |
||
26 | private $inPeers = []; |
||
27 | |||
28 | /** |
||
29 | * @var int |
||
30 | */ |
||
31 | private $nOutPeers = 0; |
||
32 | |||
33 | /** |
||
34 | * @var int |
||
35 | */ |
||
36 | private $nInPeers = 0; |
||
37 | |||
38 | /** |
||
39 | * Manager constructor. |
||
40 | * @param Connector $connector |
||
41 | */ |
||
42 | 6 | public function __construct(Connector $connector) |
|
46 | |||
47 | /** |
||
48 | * Store the newly connected peer, and trigger a new connection if they go away. |
||
49 | * |
||
50 | * @param Peer $peer |
||
51 | * @return Peer |
||
52 | */ |
||
53 | 3 | public function registerOutboundPeer(Peer $peer) |
|
65 | |||
66 | /** |
||
67 | * @param Peer $peer |
||
68 | */ |
||
69 | 3 | public function registerInboundPeer(Peer $peer) |
|
78 | |||
79 | /** |
||
80 | * @param Listener $listener |
||
81 | * @return $this |
||
82 | */ |
||
83 | 3 | public function registerListener(Listener $listener) |
|
91 | |||
92 | /** |
||
93 | * @param NetworkAddressInterface $address |
||
94 | * @return \React\Promise\PromiseInterface |
||
95 | * @throws \Exception |
||
96 | */ |
||
97 | 3 | public function connect(NetworkAddressInterface $address) |
|
101 | |||
102 | /** |
||
103 | * @param Locator $locator |
||
104 | * @return \React\Promise\Promise|\React\Promise\PromiseInterface |
||
105 | */ |
||
106 | 3 | public function getAnotherPeer(Locator $locator) |
|
107 | { |
||
108 | 3 | $deferred = new Deferred(); |
|
109 | |||
110 | // Otherwise, rely on the Locator. |
||
111 | try { |
||
112 | 3 | $deferred->resolve($locator->popAddress()); |
|
113 | 1 | } catch (\Exception $e) { |
|
114 | $locator->queryDnsSeeds()->then( |
||
115 | function () use ($deferred, $locator) { |
||
116 | $deferred->resolve($locator->popAddress()); |
||
117 | }, |
||
118 | function ($error) use ($deferred) { |
||
119 | return new RejectedPromise($error); |
||
120 | } |
||
121 | ); |
||
122 | } |
||
123 | |||
124 | 3 | return $deferred->promise(); |
|
125 | } |
||
126 | |||
127 | /** |
||
128 | * @param Locator $locator |
||
129 | * @return \React\Promise\Promise|\React\Promise\PromiseInterface |
||
130 | */ |
||
131 | 3 | public function attemptNextPeer(Locator $locator) |
|
132 | { |
||
133 | 3 | $attempt = new Deferred(); |
|
134 | |||
135 | 1 | $this |
|
136 | 3 | ->getAnotherPeer($locator) |
|
137 | ->then(function (NetworkAddressInterface $address) use ($attempt, $locator) { |
||
138 | 3 | return $this->connect($address)->then( |
|
139 | function (Peer $peer) use ($attempt) { |
||
140 | 3 | $this->registerOutboundPeer($peer); |
|
141 | 3 | $attempt->resolve($peer); |
|
142 | 3 | return $peer; |
|
143 | 3 | }, |
|
144 | function (\Exception $error) use ($attempt) { |
||
145 | 1 | $attempt->reject($error); |
|
146 | 2 | } |
|
147 | 1 | ); |
|
148 | }, function ($error) use ($attempt) { |
||
149 | $attempt->reject($error); |
||
150 | 3 | }); |
|
151 | |||
152 | 3 | return $attempt->promise(); |
|
153 | } |
||
154 | |||
155 | /** |
||
156 | * @param Locator $locator |
||
157 | * @param int $retries |
||
158 | * @return \React\Promise\PromiseInterface |
||
159 | */ |
||
160 | public function connectNextPeer(Locator $locator, $retries = 5) |
||
161 | { |
||
162 | 3 | $errorBack = function ($error) use ($locator, $retries) { |
|
163 | 1 | $allowContinue = false; |
|
164 | 1 | if ($error instanceof \RuntimeException && $error->getMessage() === "Connection refused") { |
|
165 | 1 | $allowContinue = true; |
|
166 | } |
||
167 | |||
168 | 1 | if ($error instanceof TimeoutException) { |
|
169 | 1 | $allowContinue = true; |
|
170 | } |
||
171 | |||
172 | 1 | if (!$allowContinue) { |
|
173 | throw $error; |
||
174 | } |
||
175 | |||
176 | 1 | if (0 >= $retries) { |
|
177 | throw new \RuntimeException("Connection to peers failed: too many retries"); |
||
178 | } |
||
179 | |||
180 | 1 | return $this->connectNextPeer($locator, $retries - 1); |
|
181 | 3 | }; |
|
182 | |||
183 | 1 | return $this |
|
184 | 3 | ->attemptNextPeer($locator) |
|
185 | 3 | ->then(null, $errorBack); |
|
186 | } |
||
187 | |||
188 | /** |
||
189 | * @param Locator $locator |
||
190 | * @param int $n |
||
191 | * @return \React\Promise\Promise |
||
192 | */ |
||
193 | 3 | public function connectToPeers(Locator $locator, $n) |
|
202 | } |
||
203 |