/** * {@inheritdoc} */ public function listen(callable $action) : Awaitable { return new Coroutine(function () use($action) { $factory = clone $this->factory; $factory->setTcpNoDelay(true); $this->server = (yield $factory->createSocketServer()); $port = $this->server->getPort(); $peer = $this->server->getAddress() . ($port ? ':' . $port : ''); $context = new HttpDriverContext($peer, $factory->getPeerName(), $factory->isEncrypted(), $this->middlewares, $this->responders); $pending = new \SplObjectStorage(); try { (yield $this->server->listen(function (SocketStream $socket) use($pending, $context, $action) { $conn = new Connection($socket, $context); if ($this->logger) { $conn->setLogger($this->logger); } $pending->attach($conn); while (null !== ($next = (yield $conn->nextRequest()))) { new Coroutine($this->processRequest($conn, $context, $action, ...$next)); } })); } finally { $this->server = null; foreach ($pending as $task) { $task->cancel(new \RuntimeException('FCGI server stopped')); } } }); }