/** * {@inheritdoc} */ public function connect(string $domain, int $port = null, array $options = []) : \Generator { // Check if $domain is actually an IP address. if (preg_match(self::IP_REGEX, $domain)) { return yield from $this->connector->connect($domain, $port, $options); } $options = array_merge(['name' => $domain], $options); try { $ips = (yield from $this->resolver->resolve($domain, $options)); } catch (DnsException $exception) { throw new FailureException(sprintf('Could not resolve host %s.', $domain), 0, $exception); } if (empty($ips)) { throw new FailureException(sprintf('Host for %s not found.', $domain)); } foreach ($ips as $ip) { try { return yield from $this->connector->connect($ip, $port, $options); } catch (TimeoutException $exception) { // Connection timed out, try next IP address. } catch (FailureException $exception) { // Connection failed, try next IP address. } } throw new FailureException(sprintf('Could not connect to %s:%d.', $domain, $port), 0, $exception); }
/** * {@inheritdoc} */ public function execute(string $name, $type, array $options = []) : \Generator { $timeout = isset($options['timeout']) ? (double) $options['timeout'] : self::DEFAULT_TIMEOUT; $retries = isset($options['retries']) ? (int) $options['retries'] : self::DEFAULT_RETRIES; if (0 > $retries) { $retries = 0; } $question = $this->createQuestion($name, $type); $request = $this->createRequest($question); $data = $this->encoder->encode($request); /** @var \Icicle\Socket\Socket $socket */ $socket = (yield from $this->connector->connect($this->address, $this->port, ['protocol' => self::PROTOCOL])); try { $attempt = 0; do { try { yield from $socket->write($data); $response = (yield from $socket->read(self::MAX_PACKET_SIZE, null, $timeout)); try { $response = $this->decoder->decode($response); } catch (\Exception $exception) { throw new FailureException($exception); // Wrap in more specific exception. } if (0 !== $response->getResponseCode()) { throw new ResponseCodeException($response); } if ($response->getId() !== $request->getId()) { throw new ResponseIdException($response); } return $response; } catch (TimeoutException $exception) { // Ignore timeout and try the request again. } } while (++$attempt <= $retries); throw new NoResponseException('No response from server.'); } finally { $socket->close(); } }