. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License version 3, * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ namespace Espo\Core\WebSocket; use Espo\Core\Utils\Metadata; use React\EventLoop\Factory as EventLoopFactory; use React\Socket\Server as SocketServer; use React\Socket\SecureServer as SocketSecureServer; use Ratchet\Server\IoServer; use Ratchet\Http\HttpServer; use Ratchet\WebSocket\WsServer; /** * Starts a web-socket server. */ class ServerStarter { /** @var array> */ private array $categoriesData; private ?string $phpExecutablePath; private bool $isDebugMode; private bool $useSecureServer; private string $port; public function __construct( private Subscriber $subscriber, private ConfigDataProvider $configDataProvider, Metadata $metadata ) { $this->categoriesData = $metadata->get(['app', 'webSocket', 'categories'], []); $this->phpExecutablePath = $this->configDataProvider->getPhpExecutablePath(); $this->isDebugMode = $this->configDataProvider->isDebugMode(); $this->useSecureServer = $this->configDataProvider->useSecureServer(); $port = $this->configDataProvider->getPort(); if (!$port) { $port = $this->useSecureServer ? '8443' : '8080'; } $this->port = $port; } /** * Start a web-socket server. */ public function start(): void { $loop = EventLoopFactory::create(); $pusher = new Pusher($this->categoriesData, $this->phpExecutablePath, $this->isDebugMode); $this->subscriber->subscribe($pusher, $loop); $socketServer = new SocketServer('0.0.0.0:' . $this->port, $loop); if ($this->useSecureServer) { $sslParams = $this->getSslParams(); $socketServer = new SocketSecureServer($socketServer, $loop, $sslParams); } $wsServer = new WsServer(new Ratchet\EspoWampServer($pusher)); $wsServer->enableKeepAlive($loop, 60); new IoServer( new HttpServer($wsServer), $socketServer ); $loop->run(); } /** * @return array */ private function getSslParams(): array { $sslParams = [ 'local_cert' => $this->configDataProvider->getSslCertificateFile(), 'allow_self_signed' => $this->configDataProvider->allowSelfSignedSsl(), 'verify_peer' => false, ]; if ($this->configDataProvider->getSslCertificatePassphrase()) { $sslParams['passphrase'] = $this->configDataProvider->getSslCertificatePassphrase(); } if ($this->configDataProvider->getSslCertificateLocalPrivateKey()) { $sslParams['local_pk'] = $this->configDataProvider->getSslCertificateLocalPrivateKey(); } return $sslParams; } }