boot(); $loop = React\EventLoop\Factory::create(); $connector = new React\SocketClient\TcpConnector($loop); $stdin = new React\Stream\Stream(STDIN, $loop); fwrite(STDERR, colorize(getenv('sid'), 'yellow')." widgets before : ".\sizeToCleanSize(memory_get_usage())."\n"); // We load and register all the widgets $wrapper = \Movim\Widget\Wrapper::getInstance(); $wrapper->registerAll($bootstrap->getWidgets()); fwrite(STDERR, colorize(getenv('sid'), 'yellow')." widgets : ".\sizeToCleanSize(memory_get_usage())."\n"); $conn = null; $parser = new \Moxl\Parser; $buffer = ''; $timestamp = time(); function handleSSLErrors($errno, $errstr) { fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize($errstr, 'red')."\n"); } // Temporary linker killer $loop->addPeriodicTimer(5, function() use(&$conn, &$timestamp) { if($timestamp < time() - 3600*6) { $conn->close(); } }); // One connected ping each 5 mins /*$loop->addPeriodicTimer(5*60, function() use (&$conn) { if(isset($conn) && is_resource($conn->stream)) { $ping = new \Moxl\Xec\Action\Ping\Server; $ping->request(); $conn->write(trim(\Moxl\API::commit())); \Moxl\API::clear(); } });*/ $stdin_behaviour = function ($data) use (&$conn, $loop, &$buffer, &$connector, &$xmpp_behaviour, &$parser, &$timestamp) { if(substr($data, -1) == "") { $messages = explode("", $buffer . substr($data, 0, -1)); $buffer = ''; foreach ($messages as $message) { #fwrite(STDERR, colorize($message, 'yellow')." : ".colorize('received from the browser', 'green')."\n"); $msg = json_decode($message); if(isset($msg)) { if($msg->func == 'message' && $msg->body != '') { $msg = $msg->body; } elseif($msg->func == 'down') { $evt = new Event; $evt->runEvent('session_down'); } elseif($msg->func == 'up') { $evt = new Event; $evt->runEvent('session_up'); } elseif($msg->func == 'unregister') { \Moxl\Stanza\Stream::end(); } elseif($msg->func == 'register') { if(isset($conn) && is_resource($conn->stream)) { $conn->stream->close(); } $cd = new \Modl\ConfigDAO(); $config = $cd->get(); $port = 5222; $dns = \Moxl\Utils::resolveHost($msg->host); if(isset($dns->target) && $dns->target != null) $msg->host = $dns->target; if(isset($dns->port) && $dns->port != null) $port = $dns->port; #fwrite(STDERR, colorize('open a socket to '.$domain, 'yellow')." : ".colorize('sent to XMPP', 'green')."\n"); $connector->create(gethostbyname($msg->host), $port)->then($xmpp_behaviour); } } else { return; } $rpc = new \RPC(); $rpc->handle_json($msg); $msg = \RPC::commit(); \RPC::clear(); if(!empty($msg)) { echo base64_encode(gzcompress(json_encode($msg), 9)).""; //fwrite(STDERR, colorize(json_encode($msg), 'yellow')." : ".colorize('sent to the browser', 'green')."\n"); } $xml = \Moxl\API::commit(); \Moxl\API::clear(); if(!empty($xml) && $conn) { $conn->write(trim($xml)); #fwrite(STDERR, colorize(trim($xml), 'yellow')." : ".colorize('sent to XMPP', 'green')."\n"); } } } else { $buffer .= $data; } }; $xmpp_behaviour = function (React\Stream\Stream $stream) use (&$conn, $loop, &$stdin, $stdin_behaviour, $parser, &$timestamp) { $conn = $stream; fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize('linker launched', 'blue')."\n"); fwrite(STDERR, colorize(getenv('sid'), 'yellow')." launched : ".\sizeToCleanSize(memory_get_usage())."\n"); $stdin->removeAllListeners('data'); $stdin->on('data', $stdin_behaviour); // We define a huge buffer to prevent issues with SSL streams, see https://bugs.php.net/bug.php?id=65137 $conn->bufferSize = 1024*32; $conn->on('data', function($message) use (&$conn, $loop, $parser, &$timestamp) { if(!empty($message)) { $restart = false; #fwrite(STDERR, colorize($message, 'yellow')." : ".colorize('received', 'green')."\n"); if($message == '') { $conn->close(); $loop->stop(); } elseif($message == "" || $message == '') { $session = \Session::start(); stream_set_blocking($conn->stream, 1); stream_context_set_option($conn->stream, 'ssl', 'SNI_enabled', false); stream_context_set_option($conn->stream, 'ssl', 'peer_name', $session->get('host')); stream_context_set_option($conn->stream, 'ssl', 'allow_self_signed', true); #stream_context_set_option($conn->stream, 'ssl', 'verify_peer_name', false); #stream_context_set_option($conn->stream, 'ssl', 'verify_peer', false); set_error_handler('handleSSLErrors'); $out = stream_socket_enable_crypto($conn->stream, 1, STREAM_CRYPTO_METHOD_TLS_CLIENT); restore_error_handler(); if($out !== true) { $loop->stop(); return; } fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize('TLS enabled', 'blue')."\n"); $restart = true; } #fwrite(STDERR, colorize(getenv('sid'), 'yellow')." widgets : ".\sizeToCleanSize(memory_get_usage())."\n"); \Moxl\API::clear(); \RPC::clear(); $timestamp = time(); if(!$parser->parse($message)) { fwrite(STDERR, colorize(getenv('sid'), 'yellow')." ".$parser->getError()."\n"); } if($restart) { $session = \Session::start(); \Moxl\Stanza\Stream::init($session->get('host')); stream_set_blocking($conn->stream, 0); $restart = false; } $msg = \RPC::commit(); if(!empty($msg)) { echo base64_encode(gzcompress(json_encode($msg), 9)).""; //fwrite(STDERR, colorize(json_encode($msg).' '.strlen($msg), 'yellow')." : ".colorize('sent to browser', 'green')."\n"); } \RPC::clear(); $xml = \Moxl\API::commit(); if(!empty($xml)) { $conn->write(trim($xml)); #fwrite(STDERR, colorize(trim($xml), 'yellow')." : ".colorize('sent to XMPP', 'green')."\n"); } \Moxl\API::clear(); $loop->tick(); gc_collect_cycles(); //fwrite(STDERR, colorize(getenv('sid'), 'yellow')." end data : ".\sizeToCleanSize(memory_get_usage())."\n"); //memprof_dump_callgrind(fopen("/tmp/callgrind.out", "w")); } }); $conn->on('error', function($msg) use ($conn, $loop) { #fwrite(STDERR, colorize(serialize($msg), 'red')." : ".colorize('error', 'green')."\n"); $loop->stop(); }); $conn->on('close', function($msg) use ($conn, $loop) { #fwrite(STDERR, colorize(serialize($msg), 'red')." : ".colorize('closed', 'green')."\n"); $loop->stop(); }); // And we say that we are ready ! $obj = new \StdClass; $obj->func = 'registered'; fwrite(STDERR, 'registered'); //fwrite(STDERR, colorize(json_encode($obj).' '.strlen($obj), 'yellow')." : ".colorize('obj sent to browser', 'green')."\n"); echo base64_encode(gzcompress(json_encode($obj), 9)).""; }; $stdin->on('data', $stdin_behaviour); $stdin->on('error', function() use($loop) { $loop->stop(); } ); $stdin->on('close', function() use($loop) { $loop->stop(); } ); $loop->run();