コード例 #1
0
ファイル: Resolver.php プロジェクト: koolkode/async
 /**
  * Query DNS server for A / AAAA records in batches of 2.
  * 
  * @param string $host Host name to be resolved.
  * @return array Resolved address and expiration time.
  * 
  * @throws MultiReasonException When no IP address could be resolved.
  */
 protected function resolveHost(string $host) : \Generator
 {
     $errors = [];
     foreach (\array_chunk($this->servers, 2) as $servers) {
         $ipv4 = [];
         $ipv6 = [];
         foreach ($servers as $server) {
             if (Socket::isIPv6Supported()) {
                 $ipv6[] = new Coroutine($this->lookupAddress($server, $errors, $host, Request::TYPE_AAAA));
             }
             $ipv4[] = new Coroutine($this->lookupAddress($server, $errors, $host, Request::TYPE_A));
         }
         list($ipv4, $ipv6) = (yield new AwaitAll([$this->awaitFirstResult($ipv6, $errors), $this->awaitFirstResult($ipv4, $errors)]));
         if (empty($ipv4) && empty($ipv6)) {
             continue;
         }
         $ttl = min($ipv4['ttl'] ?? PHP_INT_MAX, $ipv6['ttl'] ?? PHP_INT_MAX);
         $ttl = max(1, min(300, $ttl));
         $address = null;
         foreach (\array_merge((array) $ipv4['ips'], (array) $ipv6['ips']) as $ip) {
             try {
                 $address = $address ? $address->mergeWith(new Address($ip)) : new Address($ip);
             } catch (\Throwable $e) {
                 $errors[] = $e;
             }
         }
         if ($address && \count($address)) {
             return ['address' => $address, 'expires' => \time() + $ttl];
         }
     }
     $error = '';
     foreach ($errors as $e) {
         $error .= \sprintf("\n+ [%s] %s", \get_class($e), $e->getMessage());
     }
     if (!empty($errors)) {
         $error .= "\n";
     }
     throw new MultiReasonException($errors, \sprintf('Unable to resolve host "%s" into an IP address%s', $host, $error));
 }