<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; use App\Classes\Protocol\{Binkp,EMSI}; use App\Classes\Sock\SocketException; use App\Classes\Sock\SocketServer; use App\Models\Setup; class ServerStart extends Command { private const LOGKEY = 'CSS'; /** * The name and signature of the console command. * * @var string */ protected $signature = 'server:start'; /** * The console command description. * * @var string */ protected $description = 'Start Server'; /** * Execute the console command. * * @return mixed * @throws \Exception */ public function handle() { Log::info(sprintf('%s:+ Server Starting (%d)',self::LOGKEY,getmypid())); $o = Setup::findOrFail(config('app.id')); $start = collect(); if ($o->optionGet(Setup::O_BINKP)) $start->put('binkp',[ 'address'=>Setup::BINKP_BIND, 'port'=>Setup::BINKP_PORT, 'class'=>new Binkp($o), ]); if ($o->optionGet(Setup::O_EMSI)) $start->put('emsi',[ 'address'=>Setup::EMSI_BIND, 'port'=>Setup::EMSI_PORT, 'class'=>new EMSI($o), ]); $children = collect(); Log::debug(sprintf('%s: # Servers [%d]',self::LOGKEY,$start->count())); if (! $start->count()) { Log::alert(sprintf('%s:- No servers configured to start',self::LOGKEY)); return; } pcntl_signal(SIGCHLD,SIG_IGN); foreach ($start as $item => $config) { Log::debug(sprintf('%s: - Starting [%s] (%d)',self::LOGKEY,$item,getmypid())); $pid = pcntl_fork(); if ($pid == -1) die('could not fork'); // We are the child if (! $pid) { Log::withContext(['pid'=>getmypid()]); Log::info(sprintf('%s: - Started [%s]',self::LOGKEY,$item)); $server = new SocketServer($config['port'],$config['address']); $server->setConnectionHandler([$config['class'],'onConnect']); try { $server->listen(); } catch (SocketException $e) { if ($e->getMessage() == 'Can\'t accept connections: "Success"') Log::debug(sprintf('%s:! Server Terminated [%s]',self::LOGKEY,$item)); else Log::emergency(sprintf('%s:! Uncaught Message: %s',self::LOGKEY,$e->getMessage())); } Log::info(sprintf('%s: - Finished: [%s]',self::LOGKEY,$item)); // Child finished we need to get out of this loop. exit; } Log::info(sprintf('%s: - Forked for [%s] (%d)',self::LOGKEY,$item,$pid)); $children->put($pid,$item); } // Wait for children to exit while ($x=$children->count()) { // Wait for children to finish $exited = pcntl_wait($status); if ($exited < 0) abort(500,'Something strange for status: '.serialize($status)); Log::info(sprintf('%s: - Exited: #%d [%s]',self::LOGKEY,$x,$children->pull($exited))); } // Done Log::debug(sprintf('%s:= Finished.',self::LOGKEY)); } }