8000 [3.0] Respect attempts and timeout from resolv.conf by WyriHaximus · Pull Request #231 · reactphp/dns · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[3.0] Respect attempts and timeout from resolv.conf #231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: 3.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/Config/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,29 @@ public static function loadResolvConfBlocking($path = null)
}
}

$matches = [];
preg_match_all('/^options.*\s*$/m', $contents, $matches);
if (isset($matches[0][0])) {
$options = preg_split('/\s+/', trim($matches[0][0]));
array_shift($options);

foreach ($options as $option) {
$value = null;
if (strpos($option, ':') !== false) {
[$option, $value] = explode(':', $option, 2);
}

switch ($option) {
case 'attempts':
$config->options->attempts = ((int) $value) > 5 ? 5 : (int) $value;
break;
case 'timeout':
$config->options->timeout = ((int) $value) > 30 ? 30 : (int) $value;
break;
}
}
}

return $config;
}

Expand Down Expand Up @@ -134,4 +157,12 @@ public static function loadWmicBlocking($command = null)
}

public $nameservers = [];
/**
* @var Options
*/
public $options;

public function __construct() {
$this->options = new Options();
}
}
17 changes: 17 additions & 0 deletions src/Config/Options.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace React\Dns\Config;

use RuntimeException;

final class Options
{
/**
* @var int<1, 5>
*/
public $attempts = 2;
/**
* @var int<1, 30>
*/
public $timeout = 5;
}
59 changes: 34 additions & 25 deletions src/Resolver/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use React\Cache\CacheInterface;
use React\Dns\Config\Config;
use React\Dns\Config\HostsFile;
use React\Dns\Config\Options;
use React\Dns\Query\CachingExecutor;
use React\Dns\Query\CoopExecutor;
use React\Dns\Query\ExecutorInterface;
Expand Down Expand Up @@ -125,54 +126,60 @@ private function createExecutor($nameserver, LoopInterface $loop)

if ($tertiary !== false) {
// 3 DNS servers given => nest first with fallback for second and third
return new CoopExecutor(
new RetryExecutor(
return $this->createTopLevelDecoratingExectors(
new FallbackExecutor(
$this->createSingleExecutor($primary, $nameserver->options, $loop),
new FallbackExecutor(
$this->createSingleExecutor($primary, $loop),
new FallbackExecutor(
$this->createSingleExecutor($secondary, $loop),
$this->createSingleExecutor($tertiary, $loop)
)
$this->createSingleExecutor($secondary, $nameserver->options, $loop),
$this->createSingleExecutor($tertiary, $nameserver->options, $loop)
)
)
),
$nameserver
);
} elseif ($secondary !== false) {
// 2 DNS servers given => fallback from first to second
return new CoopExecutor(
new RetryExecutor(
new FallbackExecutor(
$this->createSingleExecutor($primary, $loop),
$this->createSingleExecutor($secondary, $loop)
)
)
return $this->createTopLevelDecoratingExectors(
new FallbackExecutor(
$this->createSingleExecutor($primary, $nameserver->options, $loop),
$this->createSingleExecutor($secondary, $nameserver->options, $loop)
),
$nameserver
);
} else {
// 1 DNS server given => use single executor
$nameserver = $primary;
}
}

return new CoopExecutor(new RetryExecutor($this->createSingleExecutor($nameserver, $loop)));
return $this->createTopLevelDecoratingExectors($this->createSingleExecutor($nameserver, new Options(), $loop), $nameserver);
}

private function createTopLevelDecoratingExectors(ExecutorInterface $executor, $nameserver)
{
$executor = new RetryExecutor($executor, (is_string($nameserver) ? new Options() : $nameserver->options)->attempts);

return new CoopExecutor($executor);
}

/**
* @param string $nameserver
* @param Options $options
* @param LoopInterface $loop
* @return ExecutorInterface
* @throws \InvalidArgumentException for invalid DNS server address
*/
private function createSingleExecutor($nameserver, LoopInterface $loop)
private function createSingleExecutor($nameserver, Options $options, LoopInterface $loop)
{
$parts = \parse_url($nameserver);

if (isset($parts['scheme']) && $parts['scheme'] === 'tcp') {
$executor = $this->createTcpExecutor($nameserver, $loop);
$executor = $this->createTcpExecutor($nameserver, $options->timeout, $loop);
} elseif (isset($parts['scheme']) && $parts['scheme'] === 'udp') {
$executor = $this->createUdpExecutor($nameserver, $loop);
$executor = $this->createUdpExecutor($nameserver, $options->timeout, $loop);
} else {
$executor = new SelectiveTransportExecutor(
$this->createUdpExecutor($nameserver, $loop),
$this->createTcpExecutor($nameserver, $loop)
$this->createUdpExecutor($nameserver, $options->timeout, $loop),
$this->createTcpExecutor($nameserver, $options->timeout, $loop)
);
}

Expand All @@ -181,33 +188,35 @@ private function createSingleExecutor($nameserver, LoopInterface $loop)

/**
* @param string $nameserver
* @param int $timeout
* @param LoopInterface $loop
* @return TimeoutExecutor
* @throws \InvalidArgumentException for invalid DNS server address
*/
private function createTcpExecutor($nameserver, LoopInterface $loop)
private function createTcpExecutor($nameserver, int $timeout, LoopInterface $loop)
{
return new TimeoutExecutor(
new TcpTransportExecutor($nameserver, $loop),
5.0,
$timeout,
$loop
);
}

/**
* @param string $nameserver
* @param int $timeout
* @param LoopInterface $loop
* @return TimeoutExecutor
* @throws \InvalidArgumentException for invalid DNS server address
*/
private function createUdpExecutor($nameserver, LoopInterface $loop)
private function createUdpExecutor($nameserver, int $timeout, LoopInterface $loop)
{
return new TimeoutExecutor(
new UdpTransportExecutor(
$nameserver,
$loop
),
5.0,
$timeout,
$loop
);
}
Expand Down
2 changes: 2 additions & 0 deletions tests/Config/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public function testLoadsFromExplicitPath()
$config = Config::loadResolvConfBlocking(__DIR__ . '/../Fixtures/etc/resolv.conf');

$this->assertEquals(['8.8.8.8'], $config->nameservers);
$this->assertEquals(4, $config->options->attempts);
$this->assertEquals(29, $config->options->timeout);
}

public function testLoadThrowsWhenPathIsInvalid()
Expand Down
1 change: 1 addition & 0 deletions tests/Fixtures/etc/resolv.conf
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
nameserver 8.8.8.8
options timeout:29 trust-ad attempts:4
Loading
0