You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
9.3 KiB

9 years ago
10 years ago
9 years ago
9 years ago
  1. <?php
  2. require __DIR__ . '/vendor/autoload.php';
  3. define('DOCUMENT_ROOT', dirname(__FILE__));
  4. gc_enable();
  5. use Movim\Bootstrap;
  6. //memprof_enable();
  7. $bootstrap = new Bootstrap;
  8. $booted = $bootstrap->boot();
  9. $loop = React\EventLoop\Factory::create();
  10. $connector = new React\SocketClient\TcpConnector($loop);
  11. $stdin = new React\Stream\Stream(STDIN, $loop);
  12. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." widgets before : ".\sizeToCleanSize(memory_get_usage())."\n");
  13. // We load and register all the widgets
  14. $wrapper = \Movim\Widget\Wrapper::getInstance();
  15. $wrapper->registerAll($bootstrap->getWidgets());
  16. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." widgets : ".\sizeToCleanSize(memory_get_usage())."\n");
  17. $conn = null;
  18. $parser = new \Moxl\Parser;
  19. $buffer = '';
  20. $timestamp = time();
  21. function handleSSLErrors($errno, $errstr) {
  22. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize($errstr, 'red')."\n");
  23. }
  24. // Temporary linker killer
  25. $loop->addPeriodicTimer(5, function() use(&$conn, &$timestamp) {
  26. if($timestamp < time() - 3600*6) {
  27. $conn->close();
  28. }
  29. });
  30. // One connected ping each 5 mins
  31. /*$loop->addPeriodicTimer(5*60, function() use (&$conn) {
  32. if(isset($conn)
  33. && is_resource($conn->stream)) {
  34. $ping = new \Moxl\Xec\Action\Ping\Server;
  35. $ping->request();
  36. $conn->write(trim(\Moxl\API::commit()));
  37. \Moxl\API::clear();
  38. }
  39. });*/
  40. $stdin_behaviour = function ($data) use (&$conn, $loop, &$buffer, &$connector, &$xmpp_behaviour, &$parser, &$timestamp) {
  41. if(substr($data, -1) == "") {
  42. $messages = explode("", $buffer . substr($data, 0, -1));
  43. $buffer = '';
  44. foreach ($messages as $message) {
  45. #fwrite(STDERR, colorize($message, 'yellow')." : ".colorize('received from the browser', 'green')."\n");
  46. $msg = json_decode($message);
  47. if(isset($msg)) {
  48. switch ($msg->func) {
  49. case 'message':
  50. $msg = $msg->body;
  51. break;
  52. case 'ping':
  53. // And we say that we are ready !
  54. $obj = new \StdClass;
  55. $obj->func = 'pong';
  56. echo base64_encode(gzcompress(json_encode($obj), 9))."";
  57. break;
  58. case 'down':
  59. $evt = new Event;
  60. $evt->runEvent('session_down');
  61. break;
  62. case 'up':
  63. $evt = new Event;
  64. $evt->runEvent('session_up');
  65. break;
  66. case 'unregister':
  67. \Moxl\Stanza\Stream::end();
  68. if(isset($conn)) $conn->close();
  69. $loop->stop();
  70. break;
  71. case 'register':
  72. if(isset($conn)
  73. && is_resource($conn->stream)) {
  74. $conn->stream->close();
  75. }
  76. $cd = new \Modl\ConfigDAO();
  77. $config = $cd->get();
  78. $port = 5222;
  79. $dns = \Moxl\Utils::resolveHost($msg->host);
  80. if(isset($dns->target) && $dns->target != null) $msg->host = $dns->target;
  81. if(isset($dns->port) && $dns->port != null) $port = $dns->port;
  82. #fwrite(STDERR, colorize('open a socket to '.$domain, 'yellow')." : ".colorize('sent to XMPP', 'green')."\n");
  83. $ip = \Moxl\Utils::resolveIp($msg->host);
  84. $ip = (!$ip || !isset($ip->address)) ? gethostbyname($msg->host) : $ip->address;
  85. fwrite(
  86. STDERR,
  87. colorize(
  88. getenv('sid'), 'yellow')." : ".
  89. colorize('Connection to '.$msg->host.' ('.$ip.')', 'blue').
  90. "\n");
  91. $connector->create($ip, $port)->then($xmpp_behaviour);
  92. break;
  93. }
  94. } else {
  95. return;
  96. }
  97. $rpc = new \RPC();
  98. $rpc->handle_json($msg);
  99. $msg = \RPC::commit();
  100. \RPC::clear();
  101. if(!empty($msg)) {
  102. echo base64_encode(gzcompress(json_encode($msg), 9))."";
  103. //fwrite(STDERR, colorize(json_encode($msg), 'yellow')." : ".colorize('sent to the browser', 'green')."\n");
  104. }
  105. $xml = \Moxl\API::commit();
  106. \Moxl\API::clear();
  107. if(!empty($xml) && $conn) {
  108. $conn->write(trim($xml));
  109. #fwrite(STDERR, colorize(trim($xml), 'yellow')." : ".colorize('sent to XMPP', 'green')."\n");
  110. }
  111. }
  112. } else {
  113. $buffer .= $data;
  114. }
  115. };
  116. $xmpp_behaviour = function (React\Stream\Stream $stream) use (&$conn, $loop, &$stdin, $stdin_behaviour, $parser, &$timestamp) {
  117. $conn = $stream;
  118. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize('linker launched', 'blue')."\n");
  119. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." launched : ".\sizeToCleanSize(memory_get_usage())."\n");
  120. $stdin->removeAllListeners('data');
  121. $stdin->on('data', $stdin_behaviour);
  122. // We define a huge buffer to prevent issues with SSL streams, see https://bugs.php.net/bug.php?id=65137
  123. $conn->bufferSize = 1024*32;
  124. $conn->on('data', function($message) use (&$conn, $loop, $parser, &$timestamp) {
  125. if(!empty($message)) {
  126. $restart = false;
  127. #fwrite(STDERR, colorize($message, 'yellow')." : ".colorize('received', 'green')."\n");
  128. if($message == '</stream:stream>') {
  129. $conn->close();
  130. $loop->stop();
  131. } elseif($message == "<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
  132. || $message == '<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>') {
  133. $session = \Session::start();
  134. stream_set_blocking($conn->stream, 1);
  135. stream_context_set_option($conn->stream, 'ssl', 'SNI_enabled', false);
  136. stream_context_set_option($conn->stream, 'ssl', 'peer_name', $session->get('host'));
  137. stream_context_set_option($conn->stream, 'ssl', 'allow_self_signed', true);
  138. #stream_context_set_option($conn->stream, 'ssl', 'verify_peer_name', false);
  139. #stream_context_set_option($conn->stream, 'ssl', 'verify_peer', false);
  140. set_error_handler('handleSSLErrors');
  141. $out = stream_socket_enable_crypto($conn->stream, 1, STREAM_CRYPTO_METHOD_TLS_CLIENT);
  142. restore_error_handler();
  143. if($out !== true) {
  144. $loop->stop();
  145. return;
  146. }
  147. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize('TLS enabled', 'blue')."\n");
  148. $restart = true;
  149. }
  150. #fwrite(STDERR, colorize(getenv('sid'), 'yellow')." widgets : ".\sizeToCleanSize(memory_get_usage())."\n");
  151. \Moxl\API::clear();
  152. \RPC::clear();
  153. $timestamp = time();
  154. if(!$parser->parse($message)) {
  155. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." ".$parser->getError()."\n");
  156. }
  157. if($restart) {
  158. $session = \Session::start();
  159. \Moxl\Stanza\Stream::init($session->get('host'));
  160. stream_set_blocking($conn->stream, 0);
  161. $restart = false;
  162. }
  163. $msg = \RPC::commit();
  164. if(!empty($msg)) {
  165. echo base64_encode(gzcompress(json_encode($msg), 9))."";
  166. //fwrite(STDERR, colorize(json_encode($msg).' '.strlen($msg), 'yellow')." : ".colorize('sent to browser', 'green')."\n");
  167. }
  168. \RPC::clear();
  169. $xml = \Moxl\API::commit();
  170. if(!empty($xml)) {
  171. $conn->write(trim($xml));
  172. #fwrite(STDERR, colorize(trim($xml), 'yellow')." : ".colorize('sent to XMPP', 'green')."\n");
  173. }
  174. \Moxl\API::clear();
  175. $loop->tick();
  176. gc_collect_cycles();
  177. //fwrite(STDERR, colorize(getenv('sid'), 'yellow')." end data : ".\sizeToCleanSize(memory_get_usage())."\n");
  178. //memprof_dump_callgrind(fopen("/tmp/callgrind.out", "w"));
  179. }
  180. });
  181. $conn->on('error', function($msg) use ($conn, $loop) {
  182. #fwrite(STDERR, colorize(serialize($msg), 'red')." : ".colorize('error', 'green')."\n");
  183. $loop->stop();
  184. });
  185. $conn->on('close', function($msg) use ($conn, $loop) {
  186. #fwrite(STDERR, colorize(serialize($msg), 'red')." : ".colorize('closed', 'green')."\n");
  187. $loop->stop();
  188. });
  189. // And we say that we are ready !
  190. $obj = new \StdClass;
  191. $obj->func = 'registered';
  192. fwrite(STDERR, 'registered');
  193. //fwrite(STDERR, colorize(json_encode($obj).' '.strlen($obj), 'yellow')." : ".colorize('obj sent to browser', 'green')."\n");
  194. echo base64_encode(gzcompress(json_encode($obj), 9))."";
  195. };
  196. $stdin->on('data', $stdin_behaviour);
  197. $stdin->on('error', function() use($loop) { $loop->stop(); } );
  198. $stdin->on('close', function() use($loop) { $loop->stop(); } );
  199. $loop->run();