laravel-websockets/src/Console/StartWebSocketServer.php

178 lines
5.3 KiB
PHP

<?php
namespace BeyondCode\LaravelWebSockets\Console;
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
use BeyondCode\LaravelWebSockets\Facades\WebSocketsRouter;
use BeyondCode\LaravelWebSockets\Server\Logger\ConnectionLogger;
use BeyondCode\LaravelWebSockets\Server\Logger\HttpLogger;
use BeyondCode\LaravelWebSockets\Server\Logger\WebsocketsLogger;
use BeyondCode\LaravelWebSockets\Server\WebSocketServerFactory;
use BeyondCode\LaravelWebSockets\Statistics\DnsResolver;
use BeyondCode\LaravelWebSockets\Statistics\Logger\StatisticsLogger as StatisticsLoggerInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use React\Dns\Config\Config as DnsConfig;
use React\Dns\Resolver\Factory as DnsFactory;
use React\Dns\Resolver\ResolverInterface;
use React\EventLoop\Factory as LoopFactory;
use React\Http\Browser;
use React\Socket\Connector;
class StartWebSocketServer extends Command
{
protected $signature = 'websockets:serve {--host=0.0.0.0} {--port=6001} {--debug : Forces the loggers to be enabled and thereby overriding the app.debug config setting } ';
protected $description = 'Start the Laravel WebSocket Server';
/** @var \React\EventLoop\LoopInterface */
protected $loop;
/** @var int */
protected $lastRestart;
public function __construct()
{
parent::__construct();
$this->loop = LoopFactory::create();
}
public function handle()
{
$this
->configureStatisticsLogger()
->configureHttpLogger()
->configureMessageLogger()
->configureConnectionLogger()
->configureRestartTimer()
->registerEchoRoutes()
->registerCustomRoutes()
->startWebSocketServer();
}
protected function configureStatisticsLogger()
{
$connector = new Connector($this->loop, [
'dns' => $this->getDnsResolver(),
'tls' => [
'verify_peer' => config('app.env') === 'production',
'verify_peer_name' => config('app.env') === 'production',
],
]);
$browser = new Browser($this->loop, $connector);
app()->singleton(StatisticsLoggerInterface::class, function () use ($browser) {
$class = config('websockets.statistics.logger', \BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger::class);
return new $class(app(ChannelManager::class), $browser);
});
$this->loop->addPeriodicTimer(config('websockets.statistics.interval_in_seconds'), function () {
StatisticsLogger::save();
});
return $this;
}
protected function configureHttpLogger()
{
app()->singleton(HttpLogger::class, function () {
return (new HttpLogger($this->output))
->enable($this->option('debug') ?: config('app.debug'))
->verbose($this->output->isVerbose());
});
return $this;
}
protected function configureMessageLogger()
{
app()->singleton(WebsocketsLogger::class, function () {
return (new WebsocketsLogger($this->output))
->enable($this->option('debug') ?: config('app.debug'))
->verbose($this->output->isVerbose());
});
return $this;
}
protected function configureConnectionLogger()
{
app()->bind(ConnectionLogger::class, function () {
return (new ConnectionLogger($this->output))
->enable(config('app.debug'))
->verbose($this->output->isVerbose());
});
return $this;
}
public function configureRestartTimer()
{
$this->lastRestart = $this->getLastRestart();
$this->loop->addPeriodicTimer(10, function () {
if ($this->getLastRestart() !== $this->lastRestart) {
$this->loop->stop();
}
});
return $this;
}
protected function registerEchoRoutes()
{
WebSocketsRouter::echo();
return $this;
}
protected function registerCustomRoutes()
{
WebSocketsRouter::customRoutes();
return $this;
}
protected function startWebSocketServer()
{
$this->info("Starting the WebSocket server on port {$this->option('port')}...");
$routes = WebSocketsRouter::getRoutes();
/* 🛰 Start the server 🛰 */
(new WebSocketServerFactory())
->setLoop($this->loop)
->useRoutes($routes)
->setHost($this->option('host'))
->setPort($this->option('port'))
->setConsoleOutput($this->output)
->createServer()
->run();
}
protected function getDnsResolver(): ResolverInterface
{
if (! config('websockets.statistics.perform_dns_lookup')) {
return new DnsResolver;
}
$dnsConfig = DnsConfig::loadSystemConfigBlocking();
return (new DnsFactory)->createCached(
$dnsConfig->nameservers
? reset($dnsConfig->nameservers)
: '1.1.1.1',
$this->loop
);
}
protected function getLastRestart()
{
return Cache::get('beyondcode:websockets:restart', 0);
}
}