aboutsummaryrefslogtreecommitdiffhomepage
path: root/assets/php/vendor/react/dns/src/Query
diff options
context:
space:
mode:
authormarvin-borner@live.com2018-04-10 21:50:16 +0200
committermarvin-borner@live.com2018-04-10 21:54:48 +0200
commitfc9401f04a3aca5abb22f87ebc210de8afe11d32 (patch)
treeb0b310f3581764ec3955f4e496a05137a32951c3 /assets/php/vendor/react/dns/src/Query
parent286d643180672f20526f3dc3bd19d7b751e2fa97 (diff)
Initial Commit
Diffstat (limited to 'assets/php/vendor/react/dns/src/Query')
-rw-r--r--assets/php/vendor/react/dns/src/Query/CachedExecutor.php55
-rw-r--r--assets/php/vendor/react/dns/src/Query/CancellationException.php7
-rw-r--r--assets/php/vendor/react/dns/src/Query/Executor.php156
-rw-r--r--assets/php/vendor/react/dns/src/Query/ExecutorInterface.php8
-rw-r--r--assets/php/vendor/react/dns/src/Query/HostsFileExecutor.php89
-rw-r--r--assets/php/vendor/react/dns/src/Query/Query.php19
-rw-r--r--assets/php/vendor/react/dns/src/Query/RecordBag.php27
-rw-r--r--assets/php/vendor/react/dns/src/Query/RecordCache.php82
-rw-r--r--assets/php/vendor/react/dns/src/Query/RetryExecutor.php44
-rw-r--r--assets/php/vendor/react/dns/src/Query/TimeoutException.php7
-rw-r--r--assets/php/vendor/react/dns/src/Query/TimeoutExecutor.php32
11 files changed, 526 insertions, 0 deletions
diff --git a/assets/php/vendor/react/dns/src/Query/CachedExecutor.php b/assets/php/vendor/react/dns/src/Query/CachedExecutor.php
new file mode 100644
index 0000000..285936d
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/CachedExecutor.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace React\Dns\Query;
+
+use React\Dns\Model\Message;
+
+class CachedExecutor implements ExecutorInterface
+{
+ private $executor;
+ private $cache;
+
+ public function __construct(ExecutorInterface $executor, RecordCache $cache)
+ {
+ $this->executor = $executor;
+ $this->cache = $cache;
+ }
+
+ public function query($nameserver, Query $query)
+ {
+ $executor = $this->executor;
+ $cache = $this->cache;
+
+ return $this->cache
+ ->lookup($query)
+ ->then(
+ function ($cachedRecords) use ($query) {
+ return Message::createResponseWithAnswersForQuery($query, $cachedRecords);
+ },
+ function () use ($executor, $cache, $nameserver, $query) {
+ return $executor
+ ->query($nameserver, $query)
+ ->then(function ($response) use ($cache, $query) {
+ $cache->storeResponseMessage($query->currentTime, $response);
+ return $response;
+ });
+ }
+ );
+ }
+
+ /**
+ * @deprecated unused, exists for BC only
+ */
+ public function buildResponse(Query $query, array $cachedRecords)
+ {
+ return Message::createResponseWithAnswersForQuery($query, $cachedRecords);
+ }
+
+ /**
+ * @deprecated unused, exists for BC only
+ */
+ protected function generateId()
+ {
+ return mt_rand(0, 0xffff);
+ }
+}
diff --git a/assets/php/vendor/react/dns/src/Query/CancellationException.php b/assets/php/vendor/react/dns/src/Query/CancellationException.php
new file mode 100644
index 0000000..ac30f4c
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/CancellationException.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace React\Dns\Query;
+
+class CancellationException extends \RuntimeException
+{
+}
diff --git a/assets/php/vendor/react/dns/src/Query/Executor.php b/assets/php/vendor/react/dns/src/Query/Executor.php
new file mode 100644
index 0000000..4c51f2b
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/Executor.php
@@ -0,0 +1,156 @@
+<?php
+
+namespace React\Dns\Query;
+
+use React\Dns\Model\Message;
+use React\Dns\Protocol\Parser;
+use React\Dns\Protocol\BinaryDumper;
+use React\EventLoop\LoopInterface;
+use React\Promise\Deferred;
+use React\Promise;
+use React\Stream\DuplexResourceStream;
+use React\Stream\Stream;
+
+class Executor implements ExecutorInterface
+{
+ private $loop;
+ private $parser;
+ private $dumper;
+ private $timeout;
+
+ /**
+ *
+ * Note that albeit supported, the $timeout parameter is deprecated!
+ * You should pass a `null` value here instead. If you need timeout handling,
+ * use the `TimeoutConnector` instead.
+ *
+ * @param LoopInterface $loop
+ * @param Parser $parser
+ * @param BinaryDumper $dumper
+ * @param null|float $timeout DEPRECATED: timeout for DNS query or NULL=no timeout
+ */
+ public function __construct(LoopInterface $loop, Parser $parser, BinaryDumper $dumper, $timeout = 5)
+ {
+ $this->loop = $loop;
+ $this->parser = $parser;
+ $this->dumper = $dumper;
+ $this->timeout = $timeout;
+ }
+
+ public function query($nameserver, Query $query)
+ {
+ $request = Message::createRequestForQuery($query);
+
+ $queryData = $this->dumper->toBinary($request);
+ $transport = strlen($queryData) > 512 ? 'tcp' : 'udp';
+
+ return $this->doQuery($nameserver, $transport, $queryData, $query->name);
+ }
+
+ /**
+ * @deprecated unused, exists for BC only
+ */
+ public function prepareRequest(Query $query)
+ {
+ return Message::createRequestForQuery($query);
+ }
+
+ public function doQuery($nameserver, $transport, $queryData, $name)
+ {
+ // we only support UDP right now
+ if ($transport !== 'udp') {
+ return Promise\reject(new \RuntimeException(
+ 'DNS query for ' . $name . ' failed: Requested transport "' . $transport . '" not available, only UDP is supported in this version'
+ ));
+ }
+
+ $that = $this;
+ $parser = $this->parser;
+ $loop = $this->loop;
+
+ // UDP connections are instant, so try this without a timer
+ try {
+ $conn = $this->createConnection($nameserver, $transport);
+ } catch (\Exception $e) {
+ return Promise\reject(new \RuntimeException('DNS query for ' . $name . ' failed: ' . $e->getMessage(), 0, $e));
+ }
+
+ $deferred = new Deferred(function ($resolve, $reject) use (&$timer, $loop, &$conn, $name) {
+ $reject(new CancellationException(sprintf('DNS query for %s has been cancelled', $name)));
+
+ if ($timer !== null) {
+ $loop->cancelTimer($timer);
+ }
+ $conn->close();
+ });
+
+ $timer = null;
+ if ($this->timeout !== null) {
+ $timer = $this->loop->addTimer($this->timeout, function () use (&$conn, $name, $deferred) {
+ $conn->close();
+ $deferred->reject(new TimeoutException(sprintf("DNS query for %s timed out", $name)));
+ });
+ }
+
+ $conn->on('data', function ($data) use ($conn, $parser, $deferred, $timer, $loop, $name) {
+ $conn->end();
+ if ($timer !== null) {
+ $loop->cancelTimer($timer);
+ }
+
+ try {
+ $response = $parser->parseMessage($data);
+ } catch (\Exception $e) {
+ $deferred->reject($e);
+ return;
+ }
+
+ if ($response->header->isTruncated()) {
+ $deferred->reject(new \RuntimeException('DNS query for ' . $name . ' failed: The server returned a truncated result for a UDP query, but retrying via TCP is currently not supported'));
+ return;
+ }
+
+ $deferred->resolve($response);
+ });
+ $conn->write($queryData);
+
+ return $deferred->promise();
+ }
+
+ /**
+ * @deprecated unused, exists for BC only
+ */
+ protected function generateId()
+ {
+ return mt_rand(0, 0xffff);
+ }
+
+ /**
+ * @param string $nameserver
+ * @param string $transport
+ * @return \React\Stream\DuplexStreamInterface
+ */
+ protected function createConnection($nameserver, $transport)
+ {
+ $fd = @stream_socket_client("$transport://$nameserver", $errno, $errstr, 0, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT);
+ if ($fd === false) {
+ throw new \RuntimeException('Unable to connect to DNS server: ' . $errstr, $errno);
+ }
+
+ // Instantiate stream instance around this stream resource.
+ // This ought to be replaced with a datagram socket in the future.
+ // Temporary work around for Windows 10: buffer whole UDP response
+ // @coverageIgnoreStart
+ if (!class_exists('React\Stream\Stream')) {
+ // prefer DuplexResourceStream as of react/stream v0.7.0
+ $conn = new DuplexResourceStream($fd, $this->loop, -1);
+ } else {
+ // use legacy Stream class for react/stream < v0.7.0
+ $conn = new Stream($fd, $this->loop);
+ $conn->bufferSize = null;
+ }
+ // @coverageIgnoreEnd
+
+ return $conn;
+ }
+}
diff --git a/assets/php/vendor/react/dns/src/Query/ExecutorInterface.php b/assets/php/vendor/react/dns/src/Query/ExecutorInterface.php
new file mode 100644
index 0000000..2f7a635
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/ExecutorInterface.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace React\Dns\Query;
+
+interface ExecutorInterface
+{
+ public function query($nameserver, Query $query);
+}
diff --git a/assets/php/vendor/react/dns/src/Query/HostsFileExecutor.php b/assets/php/vendor/react/dns/src/Query/HostsFileExecutor.php
new file mode 100644
index 0000000..0ca58be
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/HostsFileExecutor.php
@@ -0,0 +1,89 @@
+<?php
+
+namespace React\Dns\Query;
+
+use React\Dns\Config\HostsFile;
+use React\Dns\Model\Message;
+use React\Dns\Model\Record;
+use React\Promise;
+
+/**
+ * Resolves hosts from the givne HostsFile or falls back to another executor
+ *
+ * If the host is found in the hosts file, it will not be passed to the actual
+ * DNS executor. If the host is not found in the hosts file, it will be passed
+ * to the DNS executor as a fallback.
+ */
+class HostsFileExecutor implements ExecutorInterface
+{
+ private $hosts;
+ private $fallback;
+
+ public function __construct(HostsFile $hosts, ExecutorInterface $fallback)
+ {
+ $this->hosts = $hosts;
+ $this->fallback = $fallback;
+ }
+
+ public function query($nameserver, 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
+ $records = array();
+ $expectsColon = $query->type === Message::TYPE_AAAA;
+ foreach ($this->hosts->getIpsForHost($query->name) as $ip) {
+ // ensure this is an IPv4/IPV6 address according to query type
+ if ((strpos($ip, ':') !== false) === $expectsColon) {
+ $records[] = new Record($query->name, $query->type, $query->class, 0, $ip);
+ }
+ }
+
+ if ($records) {
+ return Promise\resolve(
+ Message::createResponseWithAnswersForQuery($query, $records)
+ );
+ }
+ } elseif ($query->class === Message::CLASS_IN && $query->type === Message::TYPE_PTR) {
+ // reverse lookup: extract IPv4 or IPv6 from special `.arpa` domain
+ $ip = $this->getIpFromHost($query->name);
+
+ if ($ip !== null) {
+ $records = array();
+ foreach ($this->hosts->getHostsForIp($ip) as $host) {
+ $records[] = new Record($query->name, $query->type, $query->class, 0, $host);
+ }
+
+ if ($records) {
+ return Promise\resolve(
+ Message::createResponseWithAnswersForQuery($query, $records)
+ );
+ }
+ }
+ }
+
+ return $this->fallback->query($nameserver, $query);
+ }
+
+ private function getIpFromHost($host)
+ {
+ if (substr($host, -13) === '.in-addr.arpa') {
+ // IPv4: read as IP and reverse bytes
+ $ip = @inet_pton(substr($host, 0, -13));
+ if ($ip === false || isset($ip[4])) {
+ return null;
+ }
+
+ return inet_ntop(strrev($ip));
+ } elseif (substr($host, -9) === '.ip6.arpa') {
+ // IPv6: replace dots, reverse nibbles and interpret as hexadecimal string
+ $ip = @inet_ntop(pack('H*', strrev(str_replace('.', '', substr($host, 0, -9)))));
+ if ($ip === false) {
+ return null;
+ }
+
+ return $ip;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/assets/php/vendor/react/dns/src/Query/Query.php b/assets/php/vendor/react/dns/src/Query/Query.php
new file mode 100644
index 0000000..aef6e05
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/Query.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace React\Dns\Query;
+
+class Query
+{
+ public $name;
+ public $type;
+ public $class;
+ public $currentTime;
+
+ public function __construct($name, $type, $class, $currentTime)
+ {
+ $this->name = $name;
+ $this->type = $type;
+ $this->class = $class;
+ $this->currentTime = $currentTime;
+ }
+}
diff --git a/assets/php/vendor/react/dns/src/Query/RecordBag.php b/assets/php/vendor/react/dns/src/Query/RecordBag.php
new file mode 100644
index 0000000..358cf5d
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/RecordBag.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace React\Dns\Query;
+
+use React\Dns\Model\Message;
+use React\Dns\Model\Record;
+
+class RecordBag
+{
+ private $records = array();
+
+ public function set($currentTime, Record $record)
+ {
+ $this->records[$record->data] = array($currentTime + $record->ttl, $record);
+ }
+
+ public function all()
+ {
+ return array_values(array_map(
+ function ($value) {
+ list($expiresAt, $record) = $value;
+ return $record;
+ },
+ $this->records
+ ));
+ }
+}
diff --git a/assets/php/vendor/react/dns/src/Query/RecordCache.php b/assets/php/vendor/react/dns/src/Query/RecordCache.php
new file mode 100644
index 0000000..b8142d3
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/RecordCache.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace React\Dns\Query;
+
+use React\Cache\CacheInterface;
+use React\Dns\Model\Message;
+use React\Dns\Model\Record;
+use React\Promise;
+
+class RecordCache
+{
+ private $cache;
+ private $expiredAt;
+
+ public function __construct(CacheInterface $cache)
+ {
+ $this->cache = $cache;
+ }
+
+ public function lookup(Query $query)
+ {
+ $id = $this->serializeQueryToIdentity($query);
+
+ $expiredAt = $this->expiredAt;
+
+ return $this->cache
+ ->get($id)
+ ->then(function ($value) use ($query, $expiredAt) {
+ $recordBag = unserialize($value);
+
+ if (null !== $expiredAt && $expiredAt <= $query->currentTime) {
+ return Promise\reject();
+ }
+
+ return $recordBag->all();
+ });
+ }
+
+ public function storeResponseMessage($currentTime, Message $message)
+ {
+ foreach ($message->answers as $record) {
+ $this->storeRecord($currentTime, $record);
+ }
+ }
+
+ public function storeRecord($currentTime, Record $record)
+ {
+ $id = $this->serializeRecordToIdentity($record);
+
+ $cache = $this->cache;
+
+ $this->cache
+ ->get($id)
+ ->then(
+ function ($value) {
+ return unserialize($value);
+ },
+ function ($e) {
+ return new RecordBag();
+ }
+ )
+ ->then(function ($recordBag) use ($id, $currentTime, $record, $cache) {
+ $recordBag->set($currentTime, $record);
+ $cache->set($id, serialize($recordBag));
+ });
+ }
+
+ public function expire($currentTime)
+ {
+ $this->expiredAt = $currentTime;
+ }
+
+ public function serializeQueryToIdentity(Query $query)
+ {
+ return sprintf('%s:%s:%s', $query->name, $query->type, $query->class);
+ }
+
+ public function serializeRecordToIdentity(Record $record)
+ {
+ return sprintf('%s:%s:%s', $record->name, $record->type, $record->class);
+ }
+}
diff --git a/assets/php/vendor/react/dns/src/Query/RetryExecutor.php b/assets/php/vendor/react/dns/src/Query/RetryExecutor.php
new file mode 100644
index 0000000..90353e5
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/RetryExecutor.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace React\Dns\Query;
+
+use React\Promise\Deferred;
+
+class RetryExecutor implements ExecutorInterface
+{
+ private $executor;
+ private $retries;
+
+ public function __construct(ExecutorInterface $executor, $retries = 2)
+ {
+ $this->executor = $executor;
+ $this->retries = $retries;
+ }
+
+ public function query($nameserver, Query $query)
+ {
+ return $this->tryQuery($nameserver, $query, $this->retries);
+ }
+
+ public function tryQuery($nameserver, Query $query, $retries)
+ {
+ $that = $this;
+ $errorback = function ($error) use ($nameserver, $query, $retries, $that) {
+ if (!$error instanceof TimeoutException) {
+ throw $error;
+ }
+ if (0 >= $retries) {
+ throw new \RuntimeException(
+ sprintf("DNS query for %s failed: too many retries", $query->name),
+ 0,
+ $error
+ );
+ }
+ return $that->tryQuery($nameserver, $query, $retries-1);
+ };
+
+ return $this->executor
+ ->query($nameserver, $query)
+ ->then(null, $errorback);
+ }
+}
diff --git a/assets/php/vendor/react/dns/src/Query/TimeoutException.php b/assets/php/vendor/react/dns/src/Query/TimeoutException.php
new file mode 100644
index 0000000..90bf806
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/TimeoutException.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace React\Dns\Query;
+
+class TimeoutException extends \Exception
+{
+}
diff --git a/assets/php/vendor/react/dns/src/Query/TimeoutExecutor.php b/assets/php/vendor/react/dns/src/Query/TimeoutExecutor.php
new file mode 100644
index 0000000..6a44888
--- /dev/null
+++ b/assets/php/vendor/react/dns/src/Query/TimeoutExecutor.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace React\Dns\Query;
+
+use React\EventLoop\LoopInterface;
+use React\Promise\Deferred;
+use React\Promise\CancellablePromiseInterface;
+use React\Promise\Timer;
+
+class TimeoutExecutor implements ExecutorInterface
+{
+ private $executor;
+ private $loop;
+ private $timeout;
+
+ public function __construct(ExecutorInterface $executor, $timeout, LoopInterface $loop)
+ {
+ $this->executor = $executor;
+ $this->loop = $loop;
+ $this->timeout = $timeout;
+ }
+
+ public function query($nameserver, Query $query)
+ {
+ return Timer\timeout($this->executor->query($nameserver, $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);
+ }
+ throw $e;
+ });
+ }
+}