@@ -65,9 +65,8 @@ public function __construct(LoopInterface $loop, ConnectorInterface $connector,
65
65
66
66
public function connect ()
67
67
{
68
- $ timer = null ;
69
68
$ that = $ this ;
70
- return new Promise \Promise (function ($ resolve , $ reject ) use ($ that, & $ timer ) {
69
+ return new Promise \Promise (function ($ resolve , $ reject ) use ($ that ) {
71
70
$ lookupResolve = function ($ type ) use ($ that , $ resolve , $ reject ) {
72
71
return function (array $ ips ) use ($ that , $ type , $ resolve , $ reject ) {
73
72
unset($ that ->resolverPromises [$ type ]);
@@ -83,36 +82,36 @@ public function connect()
83
82
};
84
83
85
84
$ that ->resolverPromises [Message::TYPE_AAAA ] = $ that ->resolve (Message::TYPE_AAAA , $ reject )->then ($ lookupResolve (Message::TYPE_AAAA ));
86
- $ that ->resolverPromises [Message::TYPE_A ] = $ that ->resolve (Message::TYPE_A , $ reject )->then (function (array $ ips ) use ($ that, & $ timer ) {
85
+ $ that ->resolverPromises [Message::TYPE_A ] = $ that ->resolve (Message::TYPE_A , $ reject )->then (function (array $ ips ) use ($ that ) {
87
86
// happy path: IPv6 has resolved already (or could not resolve), continue with IPv4 addresses
88
87
if ($ that ->resolved [Message::TYPE_AAAA ] === true || !$ ips ) {
89
88
return $ ips ;
90
89
}
91
90
92
91
// Otherwise delay processing IPv4 lookup until short timer passes or IPv6 resolves in the meantime
93
- $ deferred = new Promise \Deferred ();
92
+ $ deferred = new Promise \Deferred (function () use (&$ ips ) {
93
+ // discard all IPv4 addresses if cancelled
94
+ $ ips = array ();
95
+ });
94
96
$ timer = $ that ->loop ->addTimer ($ that ::RESOLUTION_DELAY , function () use ($ deferred , $ ips ) {
95
97
$ deferred ->resolve ($ ips );
96
98
});
97
99
98
- $ that ->resolverPromises [Message::TYPE_AAAA ]->then (function () use ($ that , $ timer , $ deferred , $ ips ) {
100
+ $ that ->resolverPromises [Message::TYPE_AAAA ]->then (function () use ($ that , $ timer , $ deferred , & $ ips ) {
99
101
$ that ->loop ->cancelTimer ($ timer );
100
102
$ deferred ->resolve ($ ips );
101
103
});
102
104
103
105
return $ deferred ->promise ();
104
106
})->then ($ lookupResolve (Message::TYPE_A ));
105
- }, function ($ _ , $ reject ) use ($ that, & $ timer ) {
107
+ }, function ($ _ , $ reject ) use ($ that ) {
106
108
$ reject (new \RuntimeException (
107
109
'Connection to ' . $ that ->uri . ' cancelled ' . (!$ that ->connectionPromises ? ' during DNS lookup ' : '' ) . ' (ECONNABORTED) ' ,
108
110
\defined ('SOCKET_ECONNABORTED ' ) ? \SOCKET_ECONNABORTED : 103
109
111
));
110
112
$ _ = $ reject = null ;
111
113
112
114
$ that ->cleanUp ();
113
- if ($ timer instanceof TimerInterface) {
114
- $ that ->loop ->cancelTimer ($ timer );
115
- }
116
115
});
117
116
}
118
117
@@ -247,13 +246,15 @@ public function cleanUp()
247
246
// clear list of outstanding IPs to avoid creating new connections
248
247
$ this ->connectQueue = array ();
249
248
249
+ // cancel pending connection attempts
250
250
foreach ($ this ->connectionPromises as $ connectionPromise ) {
251
251
if ($ connectionPromise instanceof PromiseInterface && \method_exists ($ connectionPromise , 'cancel ' )) {
252
252
$ connectionPromise ->cancel ();
253
253
}
254
254
}
255
255
256
- foreach ($ this ->resolverPromises as $ resolverPromise ) {
256
+ // cancel pending DNS resolution (cancel IPv4 first in case it is awaiting IPv6 resolution delay)
257
+ foreach (\array_reverse ($ this ->resolverPromises ) as $ resolverPromise ) {
257
258
if ($ resolverPromise instanceof PromiseInterface && \method_exists ($ resolverPromise , 'cancel ' )) {
258
259
$ resolverPromise ->cancel ();
259
260
}
0 commit comments