Skip to content

Commit 53f9e19

Browse files
committed
Work around DNS timeout issues for Windows users
1 parent 4646633 commit 53f9e19

2 files changed

Lines changed: 26 additions & 5 deletions

File tree

src/Query/Executor.php

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
use React\Dns\Protocol\BinaryDumper;
88
use React\EventLoop\LoopInterface;
99
use React\Promise\Deferred;
10-
use React\Socket\Connection;
1110
use React\Promise;
11+
use React\Stream\DuplexResourceStream;
12+
use React\Stream\Stream;
1213

1314
class Executor implements ExecutorInterface
1415
{
@@ -71,7 +72,7 @@ public function doQuery($nameserver, $transport, $queryData, $name)
7172
try {
7273
$conn = $this->createConnection($nameserver, $transport);
7374
} catch (\Exception $e) {
74-
return Promise\reject(new \RuntimeException('DNS query for ' . $name . ' failed: Unable to connect to DNS server: ' . $e->getMessage(), 0, $e));
75+
return Promise\reject(new \RuntimeException('DNS query for ' . $name . ' failed: ' . $e->getMessage(), 0, $e));
7576
}
7677

7778
$deferred = new Deferred(function ($resolve, $reject) use (&$timer, $loop, &$conn, $name) {
@@ -124,11 +125,31 @@ protected function generateId()
124125
return mt_rand(0, 0xffff);
125126
}
126127

128+
/**
129+
* @param string $nameserver
130+
* @param string $transport
131+
* @return \React\Stream\DuplexStreamInterface
132+
*/
127133
protected function createConnection($nameserver, $transport)
128134
{
129135
$fd = @stream_socket_client("$transport://$nameserver", $errno, $errstr, 0, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT);
130-
$conn = new Connection($fd, $this->loop);
131-
$conn->bufferSize = null; // Temporary fix for Windows 10 users
136+
if ($fd === false) {
137+
throw new \RuntimeException('Unable to connect to DNS server: ' . $errstr, $errno);
138+
}
139+
140+
// Instantiate stream instance around this stream resource.
141+
// This ought to be replaced with a datagram socket in the future.
142+
// Temporary work around for Windows 10: buffer whole UDP response
143+
// @coverageIgnoreStart
144+
if (!class_exists('React\Stream\Stream')) {
145+
// prefer DuplexResourceStream as of react/stream v0.7.0
146+
$conn = new DuplexResourceStream($fd, $this->loop, -1);
147+
} else {
148+
// use legacy Stream class for react/stream < v0.7.0
149+
$conn = new Stream($fd, $this->loop);
150+
$conn->bufferSize = null;
151+
}
152+
// @coverageIgnoreEnd
132153

133154
return $conn;
134155
}

tests/Query/ExecutorTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public function resolveShouldFailIfUdpThrow()
149149
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
150150
$promise = $this->executor->query('8.8.8.8:53', $query);
151151

152-
$this->setExpectedException('RuntimeException', 'DNS query for igor.io failed: Unable to connect to DNS server: Nope');
152+
$this->setExpectedException('RuntimeException', 'DNS query for igor.io failed: Nope');
153153
Block\await($promise, $this->loop);
154154
}
155155

0 commit comments

Comments
 (0)