Skip to content
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

Move $nameserver from ExecutorInterface to UdpTransportExecutor #135

Merged
merged 1 commit into from
Jul 11, 2019
Merged
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
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,9 @@ The following example looks up the `IPv6` address for `igor.io`.

```php
$loop = Factory::create();
$executor = new UdpTransportExecutor($loop);
$executor = new UdpTransportExecutor('8.8.8.8:53', $loop);

$executor->query(
'8.8.8.8:53',
new Query($name, Message::TYPE_AAAA, Message::CLASS_IN)
)->then(function (Message $message) {
foreach ($message->answers as $answer) {
Expand All @@ -229,7 +228,7 @@ want to use this in combination with a `TimeoutExecutor` like this:

```php
$executor = new TimeoutExecutor(
new UdpTransportExecutor($loop),
new UdpTransportExecutor($nameserver, $loop),
3.0,
$loop
);
Expand All @@ -242,7 +241,7 @@ combination with a `RetryExecutor` like this:
```php
$executor = new RetryExecutor(
new TimeoutExecutor(
new UdpTransportExecutor($loop),
new UdpTransportExecutor($nameserver, $loop),
3.0,
$loop
)
Expand All @@ -261,7 +260,7 @@ a `CoopExecutor` like this:
$executor = new CoopExecutor(
new RetryExecutor(
new TimeoutExecutor(
new UdpTransportExecutor($loop),
new UdpTransportExecutor($nameserver, $loop),
3.0,
$loop
)
Expand All @@ -284,11 +283,10 @@ use this code:
```php
$hosts = \React\Dns\Config\HostsFile::loadFromPathBlocking();

$executor = new UdpTransportExecutor($loop);
$executor = new UdpTransportExecutor('8.8.8.8:53', $loop);
$executor = new HostsFileExecutor($hosts, $executor);

$executor->query(
'8.8.8.8:53',
new Query('localhost', Message::TYPE_A, Message::CLASS_IN)
);
```
Expand Down
6 changes: 3 additions & 3 deletions examples/91-query-a-and-aaaa.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@
require __DIR__ . '/../vendor/autoload.php';

$loop = Factory::create();
$executor = new UdpTransportExecutor($loop);
$executor = new UdpTransportExecutor('8.8.8.8:53', $loop);

$name = isset($argv[1]) ? $argv[1] : 'www.google.com';

$ipv4Query = new Query($name, Message::TYPE_A, Message::CLASS_IN);
$ipv6Query = new Query($name, Message::TYPE_AAAA, Message::CLASS_IN);

$executor->query('8.8.8.8:53', $ipv4Query)->then(function (Message $message) {
$executor->query($ipv4Query)->then(function (Message $message) {
foreach ($message->answers as $answer) {
echo 'IPv4: ' . $answer->data . PHP_EOL;
}
}, 'printf');
$executor->query('8.8.8.8:53', $ipv6Query)->then(function (Message $message) {
$executor->query($ipv6Query)->then(function (Message $message) {
foreach ($message->answers as $answer) {
echo 'IPv6: ' . $answer->data . PHP_EOL;
}
Expand Down
4 changes: 2 additions & 2 deletions examples/92-query-any.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
require __DIR__ . '/../vendor/autoload.php';

$loop = Factory::create();
$executor = new UdpTransportExecutor($loop);
$executor = new UdpTransportExecutor('8.8.8.8:53', $loop);

$name = isset($argv[1]) ? $argv[1] : 'google.com';

$any = new Query($name, Message::TYPE_ANY, Message::CLASS_IN);

$executor->query('8.8.8.8:53', $any)->then(function (Message $message) {
$executor->query($any)->then(function (Message $message) {
foreach ($message->answers as $answer) {
/* @var $answer Record */

Expand Down
8 changes: 4 additions & 4 deletions src/Query/CachingExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,24 @@ public function __construct(ExecutorInterface $executor, CacheInterface $cache)
$this->cache = $cache;
}

public function query($nameserver, Query $query)
public function query(Query $query)
{
$id = $query->name . ':' . $query->type . ':' . $query->class;
$cache = $this->cache;
$that = $this;
$executor = $this->executor;

$pending = $cache->get($id);
return new Promise(function ($resolve, $reject) use ($nameserver, $query, $id, $cache, $executor, &$pending, $that) {
return new Promise(function ($resolve, $reject) use ($query, $id, $cache, $executor, &$pending, $that) {
$pending->then(
function ($message) use ($nameserver, $query, $id, $cache, $executor, &$pending, $that) {
function ($message) use ($query, $id, $cache, $executor, &$pending, $that) {
// return cached response message on cache hit
if ($message !== null) {
return $message;
}

// perform DNS lookup if not already cached
return $pending = $executor->query($nameserver, $query)->then(
return $pending = $executor->query($query)->then(
function (Message $message) use ($cache, $id, $that) {
// DNS response message received => store in cache when not truncated and return
if (!$message->tc) {
Expand Down
6 changes: 3 additions & 3 deletions src/Query/CoopExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* $executor = new CoopExecutor(
* new RetryExecutor(
* new TimeoutExecutor(
* new UdpTransportExecutor($loop),
* new UdpTransportExecutor($nameserver, $loop),
* 3.0,
* $loop
* )
Expand All @@ -46,7 +46,7 @@ public function __construct(ExecutorInterface $base)
$this->executor = $base;
}

public function query($nameserver, Query $query)
public function query(Query $query)
{
$key = $this->serializeQueryToIdentity($query);
if (isset($this->pending[$key])) {
Expand All @@ -55,7 +55,7 @@ public function query($nameserver, Query $query)
++$this->counts[$key];
} else {
// no such query pending, so start new query and keep reference until it's fulfilled or rejected
$promise = $this->executor->query($nameserver, $query);
$promise = $this->executor->query($query);
$this->pending[$key] = $promise;
$this->counts[$key] = 1;

Expand Down
2 changes: 1 addition & 1 deletion src/Query/ExecutorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

interface ExecutorInterface
{
public function query($nameserver, Query $query);
public function query(Query $query);
}
4 changes: 2 additions & 2 deletions src/Query/HostsFileExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function __construct(HostsFile $hosts, ExecutorInterface $fallback)
$this->fallback = $fallback;
}

public function query($nameserver, Query $query)
public function query(Query $query)
{
if ($query->class === Message::CLASS_IN && ($query->type === Message::TYPE_A || $query->type === Message::TYPE_AAAA)) {
// forward lookup for type A or AAAA
Expand Down Expand Up @@ -61,7 +61,7 @@ public function query($nameserver, Query $query)
}
}

return $this->fallback->query($nameserver, $query);
return $this->fallback->query($query);
}

private function getIpFromHost($host)
Expand Down
12 changes: 6 additions & 6 deletions src/Query/RetryExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ public function __construct(ExecutorInterface $executor, $retries = 2)
$this->retries = $retries;
}

public function query($nameserver, Query $query)
public function query(Query $query)
{
return $this->tryQuery($nameserver, $query, $this->retries);
return $this->tryQuery($query, $this->retries);
}

public function tryQuery($nameserver, Query $query, $retries)
public function tryQuery(Query $query, $retries)
{
$deferred = new Deferred(function () use (&$promise) {
if ($promise instanceof CancellablePromiseInterface) {
Expand All @@ -35,7 +35,7 @@ public function tryQuery($nameserver, Query $query, $retries)
};

$executor = $this->executor;
$errorback = function ($e) use ($deferred, &$promise, $nameserver, $query, $success, &$errorback, &$retries, $executor) {
$errorback = function ($e) use ($deferred, &$promise, $query, $success, &$errorback, &$retries, $executor) {
if (!$e instanceof TimeoutException) {
$errorback = null;
$deferred->reject($e);
Expand All @@ -62,14 +62,14 @@ public function tryQuery($nameserver, Query $query, $retries)
$r->setValue($e, $trace);
} else {
--$retries;
$promise = $executor->query($nameserver, $query)->then(
$promise = $executor->query($query)->then(
$success,
$errorback
);
}
};

$promise = $this->executor->query($nameserver, $query)->then(
$promise = $this->executor->query($query)->then(
$success,
$errorback
);
Expand Down
4 changes: 2 additions & 2 deletions src/Query/TimeoutExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public function __construct(ExecutorInterface $executor, $timeout, LoopInterface
$this->timeout = $timeout;
}

public function query($nameserver, Query $query)
public function query(Query $query)
{
return Timer\timeout($this->executor->query($nameserver, $query), $this->timeout, $this->loop)->then(null, function ($e) use ($query) {
return Timer\timeout($this->executor->query($query), $this->timeout, $this->loop)->then(null, function ($e) use ($query) {
if ($e instanceof Timer\TimeoutException) {
$e = new TimeoutException(sprintf("DNS query for %s timed out", $query->name), 0, $e);
}
Expand Down
27 changes: 19 additions & 8 deletions src/Query/UdpTransportExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@
*
* ```php
* $loop = Factory::create();
* $executor = new UdpTransportExecutor($loop);
* $executor = new UdpTransportExecutor('8.8.8.8:53', $loop);
*
* $executor->query(
* '8.8.8.8:53',
* new Query($name, Message::TYPE_AAAA, Message::CLASS_IN)
* )->then(function (Message $message) {
* foreach ($message->answers as $answer) {
Expand All @@ -40,7 +39,7 @@
*
* ```php
* $executor = new TimeoutExecutor(
* new UdpTransportExecutor($loop),
* new UdpTransportExecutor($nameserver, $loop),
* 3.0,
* $loop
* );
Expand All @@ -53,7 +52,7 @@
* ```php
* $executor = new RetryExecutor(
* new TimeoutExecutor(
* new UdpTransportExecutor($loop),
* new UdpTransportExecutor($nameserver, $loop),
* 3.0,
* $loop
* )
Expand All @@ -72,7 +71,7 @@
* $executor = new CoopExecutor(
* new RetryExecutor(
* new TimeoutExecutor(
* new UdpTransportExecutor($loop),
* new UdpTransportExecutor($nameserver, $loop),
* 3.0,
* $loop
* )
Expand All @@ -93,11 +92,12 @@ class UdpTransportExecutor implements ExecutorInterface
private $dumper;

/**
* @param string $nameserver
* @param LoopInterface $loop
* @param null|Parser $parser optional/advanced: DNS protocol parser to use
* @param null|BinaryDumper $dumper optional/advanced: DNS protocol dumper to use
*/
public function __construct(LoopInterface $loop, Parser $parser = null, BinaryDumper $dumper = null)
public function __construct($nameserver, LoopInterface $loop, Parser $parser = null, BinaryDumper $dumper = null)
{
if ($parser === null) {
$parser = new Parser();
Expand All @@ -106,12 +106,23 @@ public function __construct(LoopInterface $loop, Parser $parser = null, BinaryDu
$dumper = new BinaryDumper();
}

if (strpos($nameserver, '[') === false && substr_count($nameserver, ':') >= 2) {
// several colons, but not enclosed in square brackets => enclose IPv6 address in square brackets
$nameserver = '[' . $nameserver . ']';
}

$parts = parse_url('udp://' . $nameserver);
if (!isset($parts['scheme'], $parts['host']) || $parts['scheme'] !== 'udp') {
throw new \InvalidArgumentException('Invalid nameserver address given');
}

$this->nameserver = 'udp://' . $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53);
$this->loop = $loop;
$this->parser = $parser;
$this->dumper = $dumper;
}

public function query($nameserver, Query $query)
public function query(Query $query)
{
$request = Message::createRequestForQuery($query);

Expand All @@ -123,7 +134,7 @@ public function query($nameserver, Query $query)
}

// UDP connections are instant, so try connection without a loop or timeout
$socket = @\stream_socket_client("udp://$nameserver", $errno, $errstr, 0);
$socket = @\stream_socket_client($this->nameserver, $errno, $errstr, 0);
if ($socket === false) {
return \React\Promise\reject(new \RuntimeException(
'DNS query for ' . $query->name . ' failed: Unable to connect to DNS server (' . $errstr . ')',
Expand Down
39 changes: 13 additions & 26 deletions src/Resolver/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ class Factory
{
public function create($nameserver, LoopInterface $loop)
{
$nameserver = $this->addPortToServerIfMissing($nameserver);
$executor = $this->decorateHostsFileExecutor($this->createRetryExecutor($loop));
$executor = $this->decorateHostsFileExecutor($this->createRetryExecutor($nameserver, $loop));

return new Resolver($nameserver, $executor);
return new Resolver($executor);
}

public function createCached($nameserver, LoopInterface $loop, CacheInterface $cache = null)
Expand All @@ -31,10 +30,9 @@ public function createCached($nameserver, LoopInterface $loop, CacheInterface $c
$cache = new ArrayCache(256);
}

$nameserver = $this->addPortToServerIfMissing($nameserver);
$executor = $this->decorateHostsFileExecutor($this->createCachedExecutor($loop, $cache));
$executor = $this->decorateHostsFileExecutor($this->createCachedExecutor($nameserver, $loop, $cache));

return new Resolver($nameserver, $executor);
return new Resolver($executor);
}

/**
Expand Down Expand Up @@ -67,36 +65,25 @@ private function decorateHostsFileExecutor(ExecutorInterface $executor)
return $executor;
}

protected function createExecutor(LoopInterface $loop)
protected function createExecutor($nameserver, LoopInterface $loop)
{
return new TimeoutExecutor(
new UdpTransportExecutor($loop),
new UdpTransportExecutor(
$nameserver,
$loop
),
5.0,
$loop
);
}

protected function createRetryExecutor(LoopInterface $loop)
protected function createRetryExecutor($namserver, LoopInterface $loop)
{
return new CoopExecutor(new RetryExecutor($this->createExecutor($loop)));
return new CoopExecutor(new RetryExecutor($this->createExecutor($namserver, $loop)));
}

protected function createCachedExecutor(LoopInterface $loop, CacheInterface $cache)
protected function createCachedExecutor($namserver, LoopInterface $loop, CacheInterface $cache)
{
return new CachingExecutor($this->createRetryExecutor($loop), $cache);
}

protected function addPortToServerIfMissing($nameserver)
{
if (strpos($nameserver, '[') === false && substr_count($nameserver, ':') >= 2) {
// several colons, but not enclosed in square brackets => enclose IPv6 address in square brackets
$nameserver = '[' . $nameserver . ']';
}
// assume a dummy scheme when checking for the port, otherwise parse_url() fails
if (parse_url('dummy://' . $nameserver, PHP_URL_PORT) === null) {
$nameserver .= ':53';
}

return $nameserver;
return new CachingExecutor($this->createRetryExecutor($namserver, $loop), $cache);
}
}
Loading