Skip to content

Commit 6b3aa7b

Browse files
committed
Fix creating leftover connections when cancelling connection attempts
1 parent 0f2a4ec commit 6b3aa7b

File tree

3 files changed

+30
-47
lines changed

3 files changed

+30
-47
lines changed

src/HappyEyeBallsConnectionBuilder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ public function attemptConnection($ip)
251251
*/
252252
public function cleanUp()
253253
{
254+
// clear list of outstanding IPs to avoid creating new connections
255+
$this->connectQueue = array();
256+
254257
foreach ($this->connectionPromises as $connectionPromise) {
255258
if ($connectionPromise instanceof CancellablePromiseInterface) {
256259
$connectionPromise->cancel();

tests/HappyEyeBallsConnectionBuilderTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,4 +621,31 @@ public function testCleanUpCancelsAllPendingConnectionAttempts()
621621

622622
$builder->cleanUp();
623623
}
624+
625+
public function testCleanUpCancelsAllPendingConnectionAttemptsWithoutStartingNewAttemptsDueToCancellationRejection()
626+
{
627+
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
628+
629+
$connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();
630+
$connector->expects($this->once())->method('connect')->with('tcp://[::1]:80/path?test=yes&hostname=reactphp.org#start')->willReturn(new Promise(function () { }, function () {
631+
throw new \RuntimeException();
632+
}));
633+
634+
$resolver = $this->getMockBuilder('React\Dns\Resolver\ResolverInterface')->getMock();
635+
$resolver->expects($this->never())->method('resolveAll');
636+
637+
$uri = 'tcp://reactphp.org:80/path?test=yes#start';
638+
$host = 'reactphp.org';
639+
$parts = parse_url($uri);
640+
641+
$builder = new HappyEyeBallsConnectionBuilder($loop, $connector, $resolver, $uri, $host, $parts);
642+
643+
$ref = new \ReflectionProperty($builder, 'connectQueue');
644+
$ref->setAccessible(true);
645+
$ref->setValue($builder, array('::1', '::1'));
646+
647+
$builder->check($this->expectCallableNever(), function () { });
648+
649+
$builder->cleanUp();
650+
}
624651
}

tests/HappyEyeBallsConnectorTest.php

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -138,30 +138,6 @@ public function testPassThroughResolverIfGivenExplicitHost()
138138
$this->loop->run();
139139
}
140140

141-
/**
142-
* @dataProvider provideIpvAddresses
143-
*/
144-
public function testIpv4ResolvesFirstSoButIPv6IsTheFirstToConnect(array $ipv6, array $ipv4)
145-
{
146-
$this->resolver->expects($this->at(0))->method('resolveAll')->with('google.com', Message::TYPE_AAAA)->will($this->returnValue(Promise\Timer\resolve(0.001, $this->loop)->then(function () use ($ipv6) {
147-
return Promise\resolve($ipv6);
148-
})));
149-
$this->resolver->expects($this->at(1))->method('resolveAll')->with('google.com', Message::TYPE_A)->will($this->returnValue(Promise\resolve($ipv4)));
150-
$i = 0;
151-
while (count($ipv6) > 0 || count($ipv4) > 0) {
152-
if (count($ipv6) > 0) {
153-
$this->tcp->expects($this->at($i++))->method('connect')->with($this->equalTo('scheme://[' . array_shift($ipv6) . ']:80/?hostname=google.com'))->will($this->returnValue(Promise\resolve()));
154-
}
155-
if (count($ipv4) > 0) {
156-
$this->tcp->expects($this->at($i++))->method('connect')->with($this->equalTo('scheme://' . array_shift($ipv4) . ':80/?hostname=google.com'))->will($this->returnValue(Promise\resolve()));
157-
}
158-
}
159-
160-
$this->connector->connect('scheme://google.com:80/?hostname=google.com');
161-
162-
$this->loop->run();
163-
}
164-
165141
/**
166142
* @dataProvider provideIpvAddresses
167143
*/
@@ -202,29 +178,6 @@ public function testIpv6DoesntResolvesWhileIpv4DoesFirstSoIpv4Connects(array $ip
202178
$this->loop->run();
203179
}
204180

205-
/**
206-
* @dataProvider provideIpvAddresses
207-
*/
208-
public function testAttemptsToConnectBothIpv6AndIpv4Addresses(array $ipv6, array $ipv4)
209-
{
210-
$this->resolver->expects($this->at(0))->method('resolveAll')->with('google.com', Message::TYPE_AAAA)->will($this->returnValue(Promise\resolve($ipv6)));
211-
$this->resolver->expects($this->at(1))->method('resolveAll')->with('google.com', Message::TYPE_A)->will($this->returnValue(Promise\resolve($ipv4)));
212-
213-
$i = 0;
214-
while (count($ipv6) > 0 || count($ipv4) > 0) {
215-
if (count($ipv6) > 0) {
216-
$this->tcp->expects($this->at($i++))->method('connect')->with($this->equalTo('scheme://[' . array_shift($ipv6) . ']:80/?hostname=google.com'))->will($this->returnValue(Promise\resolve()));
217-
}
218-
if (count($ipv4) > 0) {
219-
$this->tcp->expects($this->at($i++))->method('connect')->with($this->equalTo('scheme://' . array_shift($ipv4) . ':80/?hostname=google.com'))->will($this->returnValue(Promise\resolve()));
220-
}
221-
}
222-
223-
$this->connector->connect('scheme://google.com:80/?hostname=google.com');
224-
225-
$this->loop->run();
226-
}
227-
228181
public function testThatTheIpv4ConnectionWillWait100MilisecondsWhenIpv6AndIpv4ResolveSimultaniously()
229182
{
230183
$timings = array();

0 commit comments

Comments
 (0)