<commit_before><?php namespace CupOfTea\TwoStream;

use App;
use ZMQ;

use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\Wamp\WampServer;
use Ratchet\WebSocket\WsServer;
use Ratchet\Server\FlashPolicy;

use React\ZMQ\Context as ZMQContext;
use React\Socket\Server as ReactServer;
use React\EventLoop\Factory as EventLoopFactory;

use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

use CupOfTea\TwoStream\Console\Output;
use CupOfTea\TwoStream\Server\Dispatcher;

class Server extends Command{
    
    const IP = '0.0.0.0';
    
    const SOCKET_PULL_ID = 'twostream.pull';
    
    /**
	 * The console command name.
	 *
	 * @var string
	 */
	protected $name = 'twostream:listen';
	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Let the WebSocket server listen on specified port for incomming connections';
    
	protected $output;
    
    protected $Dispatcher;
    
    protected $loop;
    
    protected $Ws;
    
    protected $server;
    
    protected $pull;
    
    public function __construct($Kernel){
        $this->output = new Output();
        $this->Dispatcher = new Dispatcher($Kernel, $this->output->level(3));
        
        parent::__construct();
    }
    
    public function fire(){
        ini_set('xdebug.var_display_max_depth', 4);
		$this->line('TwoStream listening on port ' . $this->option('port'));
        $this->create()->run();
    }
    
    protected function create(){
        $this->loop = EventLoopFactory::create();
        
        if($this->option('push'))
            $this->enablePush();
        
        $this->ws = new ReactServer($this->loop);
        $this->ws->listen($this->option('port'), self::IP);
        
        $this->server = new IoServer(
            new HttpServer(
                new WsServer(
                    new WampServer(
                        $this->Dispatcher
                    )
                )
            ), $this->ws
        );
        
        
        if($this->option('flash'))
            $this->allowFlash();
        
        return $this->loop;
    }
    
	/**
	 * Enable the option to push messages from
	 * the Server to the client
	 *
	 * @return void
	 */
	protected function enablePush(){
        if(!class_exists('\React\ZMQ\Context')){
            $this->error('react/zmq dependency is required if push is enabled. Stopping server', 1);
            die();
        }
        
		$context = new ZMQContext($this->loop);
        
		$this->pull = $context->getSocket(ZMQ::SOCKET_PULL, self::SOCKET_PULL_ID . '.' . App::environment());
		$this->pull->bind('tcp://127.0.0.1:' . $this->option('push-port'));
		$this->pull->on('message', array($this->latchet, 'serverPublish')); // TODO
        
        $this->info('Push enabled', 1);
	}
    
    /**
	 * Allow Flash sockets to connect to our server.
	 * For this we have to listen on flash.port (843) and return
	 * the flashpolicy
	 *
	 * @return void
	 */
	protected function allowFlash(){
		$flashSock = new ReactServer($this->loop);
		$flashSock->listen($this->option('flash-port'), self::IP);
        
		$policy = new FlashPolicy;
		$policy->addAllowedAccess('*', $this->option('port'));
        
		$webServer = new IoServer($policy, $flashSock);
        
        $this->info('Flash connections allowed', 1);
	}
    
    /**
	 * Get the console command options.
	 *
	 * @return array
	 */
	protected function getOptions(){
		return [
			['port', 'p', InputOption::VALUE_OPTIONAL, 'Port the WebSocket server should listen on', config('twostream.websocket.port')],
            ['push', null, InputOption::VALUE_OPTIONAL, 'Enable push messages from the server to the client', config('twostream.push.enabled')],
			['push-port', null, InputOption::VALUE_OPTIONAL, 'Port the push server should listen on', config('twostream.push.port')],
            ['flash', null, InputOption::VALUE_OPTIONAL, 'Allow legacy browsers to connect with the websocket polyfill', config('twostream.flash.allowed')],
			['flash-port', null, InputOption::VALUE_OPTIONAL, 'Port the push server should listen on', config('twostream.flash.port')],
        ];
	}
    
}<commit_msg>Refactored Server to be cleaner.<commit_after><?php namespace CupOfTea\TwoStream;

use App;
use ZMQ;
use Storage;

use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\Wamp\WampServer;
use Ratchet\WebSocket\WsServer;
use Ratchet\Server\FlashPolicy;

use React\ZMQ\Context as ZMQContext;
use React\Socket\Server as ReactServer;
use React\EventLoop\Factory as EventLoopFactory;

use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

use CupOfTea\TwoStream\Console\Output;
use CupOfTea\TwoStream\Server\Dispatcher;

use Illuminate\Console\AppNamespaceDetectorTrait as AppNamespaceDetector;

class Server extends Command{
    
    use AppNamespaceDetector;
    
    const IP = '0.0.0.0';
    
    const SOCKET_PULL_ID = 'twostream.pull';
    
    /**
	 * The console command name.
	 *
	 * @var string
	 */
	protected $name = 'twostream:listen';
	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Let the WebSocket server listen on specified port for incomming connections';
    
	protected $app;
    
	protected $out;
    
    protected $Kernel;
    
    protected $Dispatcher;
    
    protected $loop;
    
    protected $Ws;
    
    protected $server;
    
    protected $pull;
    
    public function __construct($app){
        parent::__construct();
        
        $this->app = $app;
        $this->out = new Output();
    }
    
    public function fire(){
        if(!$this->isInstalled())
            return $this->error('TwoStream is not installed. Please run twostream:install before attempting to run this command.');
        
        $this->line('TwoStream Server listening on port <comment>[' . $this->option('port') . ']</comment>');
        $this->boot();
        $this->start();
    }
    
    protected function start(){
        $this->loop->run();
    }
    
    protected function boot(){
        $this->buildDispatcher();
        $this->createLoop();
        
        if($this->option('push'))
            $this->enablePush();
        
        $this->bootWsServer();
        $this->bootHttpServer();
        
        if($this->option('flash'))
            $this->allowFlash();
        
        return $this->loop;
    }
    
    protected function buildKernel(){
        $this->app->singleton(
            'CupOfTea\TwoStream\Contracts\Ws\Kernel',
            $this->getAppNamespace() . 'Ws\Kernel'
        );
        
        return $this->Kernel = $this->app->make('CupOfTea\TwoStream\Contracts\Ws\Kernel');
    }
    
    protected function buildDispatcher(){
        return $this->Dispatcher = new Dispatcher($this->buildKernel(), $this->out->level(3));
    }
    
    protected function createLoop(){
        return $this->loop = EventLoopFactory::create();
    }
    
    protected function bootWsServer(){
        $this->ws = new ReactServer($this->loop);
        $this->ws->listen($this->option('port'), self::IP);
        
        return $this->ws;
    }
    
    protected function bootHttpServer(){
        return $this->server = new IoServer(
            new HttpServer(
                new WsServer(
                    new WampServer(
                        $this->Dispatcher
                    )
                )
            ), $this->ws
        );
    }
    
	/**
	 * Enable the option to push messages from
	 * the Server to the client
	 *
	 * @return void
	 */
	protected function enablePush(){
        if(!class_exists('\React\ZMQ\Context')){
            $this->error('React/ZMQ dependency is required to enable push. Stopping server.', 1);
            die();
        }
        
		$context = new ZMQContext($this->loop);
        
		$this->pull = $context->getSocket(ZMQ::SOCKET_PULL, self::SOCKET_PULL_ID . '.' . App::environment());
		$this->pull->bind('tcp://127.0.0.1:' . $this->option('push-port'));
		$this->pull->on('message', array($this->latchet, 'serverPublish')); // TODO
        
        $this->info('Push enabled', 1);
	}
    
    /**
	 * Allow Flash sockets to connect to our server.
	 * For this we have to listen on flash.port (843) and return
	 * the flashpolicy
	 *
	 * @return void
	 */
	protected function allowFlash(){
		$flashSock = new ReactServer($this->loop);
		$flashSock->listen($this->option('flash-port'), self::IP);
        
		$policy = new FlashPolicy;
		$policy->addAllowedAccess('*', $this->option('port'));
        
		$webServer = new IoServer($policy, $flashSock);
        
        $this->info('Flash connections allowed', 1);
	}
    
    /**
	 * Get the console command options.
	 *
	 * @return array
	 */
	protected function getOptions(){
		return [
			['port', 'p', InputOption::VALUE_OPTIONAL, 'Port the WebSocket server should listen on', config('twostream.websocket.port')],
            ['push', null, InputOption::VALUE_OPTIONAL, 'Enable push messages from the server to the client', config('twostream.push.enabled')],
			['push-port', null, InputOption::VALUE_OPTIONAL, 'Port the push server should listen on', config('twostream.push.port')],
            ['flash', null, InputOption::VALUE_OPTIONAL, 'Allow legacy browsers to connect with the websocket polyfill', config('twostream.flash.allowed')],
			['flash-port', null, InputOption::VALUE_OPTIONAL, 'Port the push server should listen on', config('twostream.flash.port')],
        ];
	}
    
    protected function isInstalled(){
        $disk = Storage::createLocalDriver([
            'driver' => 'local',
			'root'   => app_path(),
        ]);
        
        foreach(TwoStreamServiceProvider::pathsToPublish(strtolower(TwoStream::PACKAGE), 'required') as $required){
            if(!$disk->exists(str_replace(['.stub', app_path()], ['.php', ''], $required)))
                return false;
        }
        
        return true;
    }
    
}
{'fraction_non_alphanumeric': 0.14167166566686662, 'fraction_numerical': 0.0034993001399720057, 'mean_word_length': 2.51846640872318, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 103, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1536692', 'n_tokens_mistral': 3030, 'n_tokens_neox': 2890, 'n_words': 682}