Skip to content

Commit 2c91902

Browse files
committed
Include DNS server name when query transport fails
1 parent 7c336fe commit 2c91902

File tree

4 files changed

+52
-47
lines changed

4 files changed

+52
-47
lines changed

src/Query/TcpTransportExecutor.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public function __construct($nameserver, LoopInterface $loop)
147147
throw new \InvalidArgumentException('Invalid nameserver address given');
148148
}
149149

150-
$this->nameserver = $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53);
150+
$this->nameserver = 'tcp://' . $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53);
151151
$this->loop = $loop;
152152
$this->parser = new Parser();
153153
$this->dumper = new BinaryDumper();
@@ -177,7 +177,7 @@ public function query(Query $query)
177177
$socket = @\stream_socket_client($this->nameserver, $errno, $errstr, 0, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT);
178178
if ($socket === false) {
179179
return \React\Promise\reject(new \RuntimeException(
180-
'DNS query for ' . $query->describe() . ' failed: Unable to connect to DNS server (' . $errstr . ')',
180+
'DNS query for ' . $query->describe() . ' failed: Unable to connect to DNS server ' . $this->nameserver . ' (' . $errstr . ')',
181181
$errno
182182
));
183183
}
@@ -227,7 +227,7 @@ public function handleWritable()
227227
if ($this->readPending === false) {
228228
$name = @\stream_socket_get_name($this->socket, true);
229229
if ($name === false) {
230-
$this->closeError('Connection to DNS server rejected');
230+
$this->closeError('Connection to DNS server ' . $this->nameserver . ' rejected');
231231
return;
232232
}
233233

@@ -240,7 +240,7 @@ public function handleWritable()
240240
$error = \error_get_last();
241241
\preg_match('/errno=(\d+) (.+)/', $error['message'], $m);
242242
$this->closeError(
243-
'Unable to send query to DNS server (' . (isset($m[2]) ? $m[2] : $error['message']) . ')',
243+
'Unable to send query to DNS server ' . $this->nameserver . ' (' . (isset($m[2]) ? $m[2] : $error['message']) . ')',
244244
isset($m[1]) ? (int) $m[1] : 0
245245
);
246246
return;
@@ -264,7 +264,7 @@ public function handleRead()
264264
// any error is fatal, this is a stream of TCP/IP data
265265
$chunk = @\fread($this->socket, 65536);
266266
if ($chunk === false || $chunk === '') {
267-
$this->closeError('Connection to DNS server lost');
267+
$this->closeError('Connection to DNS server ' . $this->nameserver . ' lost');
268268
return;
269269
}
270270

@@ -286,13 +286,13 @@ public function handleRead()
286286
$response = $this->parser->parseMessage($data);
287287
} catch (\Exception $e) {
288288
// reject all pending queries if we received an invalid message from remote server
289-
$this->closeError('Invalid message received from DNS server');
289+
$this->closeError('Invalid message received from DNS server ' . $this->nameserver);
290290
return;
291291
}
292292

293293
// reject all pending queries if we received an unexpected response ID or truncated response
294294
if (!isset($this->pending[$response->id]) || $response->tc) {
295-
$this->closeError('Invalid response message received from DNS server');
295+
$this->closeError('Invalid response message received from DNS server ' . $this->nameserver);
296296
return;
297297
}
298298

src/Query/UdpTransportExecutor.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public function query(Query $query)
137137
$socket = @\stream_socket_client($this->nameserver, $errno, $errstr, 0);
138138
if ($socket === false) {
139139
return \React\Promise\reject(new \RuntimeException(
140-
'DNS query for ' . $query->describe() . ' failed: Unable to connect to DNS server (' . $errstr . ')',
140+
'DNS query for ' . $query->describe() . ' failed: Unable to connect to DNS server ' . $this->nameserver . ' (' . $errstr . ')',
141141
$errno
142142
));
143143
}
@@ -154,7 +154,7 @@ public function query(Query $query)
154154
$error = \error_get_last();
155155
\preg_match('/errno=(\d+) (.+)/', $error['message'], $m);
156156
return \React\Promise\reject(new \RuntimeException(
157-
'DNS query for ' . $query->describe() . ' failed: Unable to send query to DNS server (' . (isset($m[2]) ? $m[2] : $error['message']) . ')',
157+
'DNS query for ' . $query->describe() . ' failed: Unable to send query to DNS server ' . $this->nameserver . ' (' . (isset($m[2]) ? $m[2] : $error['message']) . ')',
158158
isset($m[1]) ? (int) $m[1] : 0
159159
));
160160
}
@@ -170,7 +170,8 @@ public function query(Query $query)
170170

171171
$max = $this->maxPacketSize;
172172
$parser = $this->parser;
173-
$loop->addReadStream($socket, function ($socket) use ($loop, $deferred, $query, $parser, $request, $max) {
173+
$nameserver = $this->nameserver;
174+
$loop->addReadStream($socket, function ($socket) use ($loop, $deferred, $query, $parser, $request, $max, $nameserver) {
174175
// try to read a single data packet from the DNS server
175176
// ignoring any errors, this is uses UDP packets and not a stream of data
176177
$data = @\fread($socket, $max);
@@ -198,7 +199,7 @@ public function query(Query $query)
198199

199200
if ($response->tc) {
200201
$deferred->reject(new \RuntimeException(
201-
'DNS query for ' . $query->describe() . ' failed: The server returned a truncated result for a UDP query',
202+
'DNS query for ' . $query->describe() . ' failed: The DNS server ' . $nameserver . ' returned a truncated result for a UDP query',
202203
\defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90
203204
));
204205
return;

tests/Query/TcpTransportExecutorTest.php

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,27 @@ public static function provideDefaultPortProvider()
3535
return array(
3636
array(
3737
'8.8.8.8',
38-
'8.8.8.8:53'
38+
'tcp://8.8.8.8:53'
3939
),
4040
array(
4141
'1.2.3.4:5',
42-
'1.2.3.4:5'
42+
'tcp://1.2.3.4:5'
4343
),
4444
array(
4545
'tcp://1.2.3.4',
46-
'1.2.3.4:53'
46+
'tcp://1.2.3.4:53'
4747
),
4848
array(
4949
'tcp://1.2.3.4:53',
50-
'1.2.3.4:53'
50+
'tcp://1.2.3.4:53'
5151
),
5252
array(
5353
'::1',
54-
'[::1]:53'
54+
'tcp://[::1]:53'
5555
),
5656
array(
5757
'[::1]:53',
58-
'[::1]:53'
58+
'tcp://[::1]:53'
5959
)
6060
);
6161
}
@@ -129,7 +129,7 @@ public function testQueryRejectsIfServerConnectionFails()
129129

130130
/** @var \RuntimeException $exception */
131131
$this->assertInstanceOf('RuntimeException', $exception);
132-
$this->assertEquals('DNS query for google.com (A) failed: Unable to connect to DNS server (Failed to parse address "///")', $exception->getMessage());
132+
$this->assertEquals('DNS query for google.com (A) failed: Unable to connect to DNS server /// (Failed to parse address "///")', $exception->getMessage());
133133
}
134134

135135
public function testQueryRejectsOnCancellationWithoutClosingSocketButStartsIdleTimer()
@@ -265,7 +265,7 @@ function ($e) use (&$exception) {
265265

266266
/** @var \RuntimeException $exception */
267267
$this->assertInstanceOf('RuntimeException', $exception);
268-
$this->assertEquals('DNS query for google.com (A) failed: Connection to DNS server rejected', $exception->getMessage());
268+
$this->assertEquals('DNS query for google.com (A) failed: Connection to DNS server tcp://127.0.0.1:1 rejected', $exception->getMessage());
269269
}
270270

271271
public function testQueryStaysPendingWhenClientCanNotSendExcessiveMessageInOneChunk()
@@ -390,7 +390,7 @@ public function testQueryRejectsWhenClientKeepsSendingWhenServerClosesSocket()
390390
// expect EPIPE (Broken pipe), except for macOS kernel race condition or legacy HHVM
391391
$this->setExpectedException(
392392
'RuntimeException',
393-
'Unable to send query to DNS server',
393+
'Unable to send query to DNS server tcp://' . $address . ' (',
394394
defined('SOCKET_EPIPE') && !defined('HHVM_VERSION') ? (PHP_OS !== 'Darwin' || $writePending ? SOCKET_EPIPE : SOCKET_EPROTOTYPE) : null
395395
);
396396
throw $exception;
@@ -411,21 +411,22 @@ public function testQueryRejectsWhenServerClosesConnection()
411411

412412
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
413413

414-
$wait = true;
414+
$exception = null;
415415
$executor->query($query)->then(
416416
null,
417-
function ($e) use (&$wait) {
418-
$wait = false;
419-
throw $e;
417+
function ($e) use (&$exception) {
418+
$exception = $e;
420419
}
421420
);
422421

423422
\Clue\React\Block\sleep(0.01, $loop);
424-
if ($wait) {
423+
if ($exception === null) {
425424
\Clue\React\Block\sleep(0.2, $loop);
426425
}
427426

428-
$this->assertFalse($wait);
427+
/** @var \RuntimeException $exception */
428+
$this->assertInstanceOf('RuntimeException', $exception);
429+
$this->assertEquals('DNS query for google.com (A) failed: Connection to DNS server tcp://' . $address . ' lost', $exception->getMessage());
429430
}
430431

431432
public function testQueryKeepsPendingIfServerSendsIncompleteMessageLength()
@@ -514,21 +515,22 @@ public function testQueryRejectsWhenServerSendsInvalidMessage()
514515

515516
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
516517

517-
$wait = true;
518+
$exception = null;
518519
$executor->query($query)->then(
519520
null,
520-
function ($e) use (&$wait) {
521-
$wait = false;
522-
throw $e;
521+
function ($e) use (&$exception) {
522+
$exception = $e;
523523
}
524524
);
525525

526526
\Clue\React\Block\sleep(0.01, $loop);
527-
if ($wait) {
527+
if ($exception === null) {
528528
\Clue\React\Block\sleep(0.2, $loop);
529529
}
530530

531-
$this->assertFalse($wait);
531+
/** @var \RuntimeException $exception */
532+
$this->assertInstanceOf('RuntimeException', $exception);
533+
$this->assertEquals('DNS query for google.com (A) failed: Invalid message received from DNS server tcp://' . $address, $exception->getMessage());
532534
}
533535

534536
public function testQueryRejectsWhenServerSendsInvalidId()
@@ -564,21 +566,22 @@ public function testQueryRejectsWhenServerSendsInvalidId()
564566

565567
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
566568

567-
$wait = true;
569+
$exception = null;
568570
$executor->query($query)->then(
569571
null,
570-
function ($e) use (&$wait) {
571-
$wait = false;
572-
throw $e;
572+
function ($e) use (&$exception) {
573+
$exception = $e;
573574
}
574575
);
575576

576577
\Clue\React\Block\sleep(0.01, $loop);
577-
if ($wait) {
578+
if ($exception === null) {
578579
\Clue\React\Block\sleep(0.2, $loop);
579580
}
580581

581-
$this->assertFalse($wait);
582+
/** @var \RuntimeException $exception */
583+
$this->assertInstanceOf('RuntimeException', $exception);
584+
$this->assertEquals('DNS query for google.com (A) failed: Invalid response message received from DNS server tcp://' . $address, $exception->getMessage());
582585
}
583586

584587
public function testQueryRejectsIfServerSendsTruncatedResponse()
@@ -614,21 +617,22 @@ public function testQueryRejectsIfServerSendsTruncatedResponse()
614617

615618
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
616619

617-
$wait = true;
620+
$exception = null;
618621
$executor->query($query)->then(
619622
null,
620-
function ($e) use (&$wait) {
621-
$wait = false;
622-
throw $e;
623+
function ($e) use (&$exception) {
624+
$exception = $e;
623625
}
624626
);
625627

626628
\Clue\React\Block\sleep(0.01, $loop);
627-
if ($wait) {
629+
if ($exception === null) {
628630
\Clue\React\Block\sleep(0.2, $loop);
629631
}
630632

631-
$this->assertFalse($wait);
633+
/** @var \RuntimeException $exception */
634+
$this->assertInstanceOf('RuntimeException', $exception);
635+
$this->assertEquals('DNS query for google.com (A) failed: Invalid response message received from DNS server tcp://' . $address, $exception->getMessage());
632636
}
633637

634638
public function testQueryResolvesIfServerSendsValidResponse()

tests/Query/UdpTransportExecutorTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public function testQueryRejectsIfServerConnectionFails()
136136

137137
$this->setExpectedException(
138138
'RuntimeException',
139-
'DNS query for google.com (A) failed: Unable to connect to DNS server (Failed to parse address "///")'
139+
'DNS query for google.com (A) failed: Unable to connect to DNS server /// (Failed to parse address "///")'
140140
);
141141
throw $exception;
142142
}
@@ -166,7 +166,7 @@ public function testQueryRejectsIfSendToServerFailsAfterConnection()
166166
// ECONNREFUSED (Connection refused) on Linux, EMSGSIZE (Message too long) on macOS
167167
$this->setExpectedException(
168168
'RuntimeException',
169-
'DNS query for ' . $query->name . ' (A) failed: Unable to send query to DNS server'
169+
'DNS query for ' . $query->name . ' (A) failed: Unable to send query to DNS server udp://0.0.0.0:53 ('
170170
);
171171
throw $exception;
172172
}
@@ -318,7 +318,7 @@ public function testQueryRejectsIfServerSendsTruncatedResponse()
318318

319319
$this->setExpectedException(
320320
'RuntimeException',
321-
'DNS query for google.com (A) failed: The server returned a truncated result for a UDP query',
321+
'DNS query for google.com (A) failed: The DNS server udp://' . $address . ' returned a truncated result for a UDP query',
322322
defined('SOCKET_EMSGSIZE') ? SOCKET_EMSGSIZE : 90
323323
);
324324
\Clue\React\Block\await($promise, $loop, 0.1);

0 commit comments

Comments
 (0)