resolve(new self($socket)); }); try { return (yield Promise\timeout($deferred->promise(), $timeout)); } catch (Amp\TimeoutException $e) { throw new TimeoutException("Name resolution timed out, could not connect to server at {$uri}"); } finally { Loop::cancel($watcher); } }); } public static function parser(callable $callback) : \Generator { $decoder = (new DecoderFactory())->create(); while (\true) { $length = (yield 2); $length = \unpack("n", $length)[1]; $rawData = (yield $length); $callback($decoder->decode($rawData)); } } protected function __construct($socket) { parent::__construct($socket); $this->encoder = (new EncoderFactory())->create(); $this->queue = new \SplQueue(); $this->parser = new Parser(self::parser([$this->queue, 'push'])); } protected function send(Message $message) : Promise { $data = $this->encoder->encode($message); $promise = $this->write(\pack("n", \strlen($data)) . $data); $promise->onResolve(function ($error) { if ($error) { $this->isAlive = \false; } }); return $promise; } protected function receive() : Promise { if ($this->queue->isEmpty()) { return call(function () { do { $chunk = (yield $this->read()); if ($chunk === null) { $this->isAlive = \false; throw new DnsException("Reading from the server failed"); } $this->parser->push($chunk); } while ($this->queue->isEmpty()); return $this->queue->shift(); }); } return new Success($this->queue->shift()); } public function isAlive() : bool { return $this->isAlive; } }