private function doStart() : \Generator
{
assert($this->logDebug("starting"));
$emitter = $this->makePrivateCallable("onParseEmit");
$writer = $this->makePrivateCallable("writeResponse");
$this->vhosts->setupHttpDrivers($emitter, $writer);
$addrCtxMap = $this->generateBindableAddressContextMap();
foreach ($addrCtxMap as $address => $context) {
$this->boundServers[$address] = $this->bind($address, $context);
}
$this->state = self::STARTING;
$notifyResult = (yield $this->notify());
if ($hadErrors = (bool) $notifyResult[0]) {
yield from $this->doStop();
throw new \RuntimeException("Server::STARTING observer initialization failure");
}
/* enable direct access for performance, but Options now shouldn't be changed as Server has been STARTED */
try {
if (@\assert(false)) {
$options = new class extends Options
{
use \Amp\Struct;
private $_initialized = false;
public function __get(string $prop)
{
throw new \DomainException($this->generateStructPropertyError($prop));
}
public function __set(string $prop, $val)
{
if ($this->_initialized) {
throw new \RuntimeException("Cannot add options after server has STARTED.");
}
$this->{$prop} = $val;
}
};
foreach ((new \ReflectionObject($this->options))->getProperties() as $property) {
$name = $property->getName();
$options->{$name} = $this->options->{$name};
}
$this->options = $options;
}
} catch (\AssertionError $e) {
}
// lock options
$this->options->_initialized = true;
$this->dropPrivileges();
$this->state = self::STARTED;
assert($this->logDebug("started"));
foreach ($this->boundServers as $serverName => $server) {
$this->acceptWatcherIds[$serverName] = \Amp\onReadable($server, $this->onAcceptable);
$this->logger->info("Listening on {$serverName}");
}
return $this->notify()->when(function ($e, $notifyResult) {
if ($hadErrors = $e || $notifyResult[0]) {
resolve($this->doStop())->when(function ($e) {
throw new \RuntimeException("Server::STARTED observer initialization failure", 0, $e);
});
}
});
}