createBaseServer($this->genConfigService($service), $daemon); if (isset($this->server->setting[Constant::OPTION_TASK_WORKER_NUM])) { $this->container->get(Task::class)->initTaskWorker($this->server); } foreach ($this->_process as $process) $this->server->addProcess($process); foreach ($service as $value) $this->addListener($value); $this->provider->on(OnServerBeforeStart::class, [$this, 'onSignal']); } /** * @return bool * @throws */ public function shutdown(): bool { $this->server->shutdown(); $this->dispatch->dispatch(new OnShutdown()); return true; } /** * @param array $service * @param int $daemon * @return array * @throws ContainerExceptionInterface * @throws NotFindClassException * @throws NotFoundExceptionInterface */ private function createBaseServer(array $service, int $daemon = 0): array { $config = array_pop($service); $match = $this->getServerClass($config->type); if (is_null($match)) { throw new NotFindClassException('Unknown server type ' . $config->type); } $this->container->get(StdoutLogger::class)->println('Listen address ' . $config->host . '::' . $config->port); $this->server = new $match($config->host, $config->port, $config->mode, $config->socket); $this->server->set($this->systemConfig($config, $daemon)); if (!isset($config->events[Constant::SHUTDOWN])) { $config->events[Constant::SHUTDOWN] = [OnServer::class, 'onShutdown']; } $this->event($this->server, array_merge(\config('servers.server.events', []), $config->events)); $this->container->bind(ServerInterface::class, $this->server); return $service; } /** * @param SConfig $config * @param int $daemon * @return array * @throws */ protected function systemConfig(SConfig $config, int $daemon): array { $settings = array_merge(\config('servers.server.settings', []), $config->settings); $settings[Constant::OPTION_DAEMONIZE] = (bool)$daemon; $settings[Constant::OPTION_ENABLE_REUSE_PORT] = true; $settings[Constant::OPTION_PID_FILE] = storage('.swoole.pid'); if (!isset($settings[Constant::OPTION_PID_FILE])) { $settings[Constant::OPTION_LOG_FILE] = storage('system.log'); } return $settings; } /** * @param SConfig $config * @return void * @throws */ public function addListener(SConfig $config): void { $port = $this->server->addlistener($config->host, $config->port, $config->socket); if ($port === false) { throw new Exception('Listen port fail.' . swoole_last_error()); } $port->set($this->resetSettings($config->type, $config->settings)); $this->event($port, $config->getEvents()); $this->container->get(StdoutLogger::class)->println('Listen address ' . $config->host . '::' . $config->port); } /** * @param string $type * @param array $settings * @return array * @throws */ private function resetSettings(string $type, array $settings): array { if ($type == Constant::SERVER_TYPE_HTTP && !isset($settings['open_http_protocol'])) { $settings['open_http_protocol'] = true; if (in_array($this->server->setting['dispatch_mode'], [2, 4])) { $settings['open_http2_protocol'] = true; } } if ($type == Constant::SERVER_TYPE_WEBSOCKET && !isset($settings['open_websocket_protocol'])) { $settings['open_websocket_protocol'] = true; } return $settings; } /** * @param Server\Port|Server $base * @param array $events * @return void * @throws */ private function event(Server\Port|Server $base, array $events): void { $container = $this->container; foreach ($events as $name => $event) { if (is_array($event) && is_string($event[0])) { $event[0] = $container->get($event[0]); } $base->on($name, $event); } } /** * @return void * @throws */ public function start(): void { $this->dispatch->dispatch(new OnServerBeforeStart()); $this->server->start(); } }