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.

205 lines
7.5 KiB

10 years ago
  1. <?php
  2. require __DIR__ . '/vendor/autoload.php';
  3. define('DOCUMENT_ROOT', dirname(__FILE__));
  4. require_once(DOCUMENT_ROOT.'/bootstrap.php');
  5. gc_enable();
  6. //memprof_enable();
  7. $bootstrap = new Bootstrap();
  8. $booted = $bootstrap->boot();
  9. $loop = React\EventLoop\Factory::create();
  10. $dnsResolverFactory = new React\Dns\Resolver\Factory();
  11. $dns = $dnsResolverFactory->createCached('8.8.8.8', $loop);
  12. $connector = new React\SocketClient\Connector($loop, $dns);
  13. $stdin = new React\Stream\Stream(STDIN, $loop);
  14. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." widgets before : ".\sizeToCleanSize(memory_get_usage())."\n");
  15. // We load and register all the widgets
  16. $wrapper = WidgetWrapper::getInstance();
  17. $wrapper->registerAll(true);
  18. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." widgets : ".\sizeToCleanSize(memory_get_usage())."\n");
  19. $conn = null;
  20. $parser = new \Moxl\Parser;
  21. $buffer = '';
  22. function handleSSLErrors($errno, $errstr) {
  23. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize($errstr, 'red')."\n");
  24. }
  25. $stdin_behaviour = function ($data) use (&$conn, $loop, &$buffer, &$connector, &$xmpp_behaviour, &$parser) {
  26. if(substr($data, -1) == "") {
  27. $messages = explode("", $buffer . substr($data, 0, -1));
  28. $buffer = '';
  29. foreach ($messages as $message) {
  30. #fwrite(STDERR, colorize($message, 'yellow')." : ".colorize('received from the browser', 'green')."\n");
  31. $msg = json_decode($message);
  32. if(isset($msg)) {
  33. if($msg->func == 'message' && $msg->body != '') {
  34. $msg = $msg->body;
  35. } elseif($msg->func == 'unregister') {
  36. \Moxl\Stanza\Stream::end();
  37. } elseif($msg->func == 'register') {
  38. $cd = new \Modl\ConfigDAO();
  39. $config = $cd->get();
  40. $port = 5222;
  41. $dns = \Moxl\Utils::resolveHost($msg->host);
  42. if(isset($dns->target) && $dns->target != null) $msg->host = $dns->target;
  43. if(isset($dns->port) && $dns->port != null) $port = $dns->port;
  44. #fwrite(STDERR, colorize('open a socket to '.$domain, 'yellow')." : ".colorize('sent to XMPP', 'green')."\n");
  45. $connector->create($msg->host, $port)->then($xmpp_behaviour);
  46. }
  47. } else {
  48. return;
  49. }
  50. $rpc = new \RPC();
  51. $rpc->handle_json($msg);
  52. $msg = \RPC::commit();
  53. \RPC::clear();
  54. if(!empty($msg)) {
  55. //echo json_encode($msg)."";
  56. echo base64_encode(gzcompress(json_encode($msg), 9))."";
  57. //fwrite(STDERR, colorize(json_encode($msg), 'yellow')." : ".colorize('sent to the browser', 'green')."\n");
  58. }
  59. $xml = \Moxl\API::commit();
  60. \Moxl\API::clear();
  61. if(!empty($xml) && $conn) {
  62. $conn->write(trim($xml));
  63. #fwrite(STDERR, colorize(trim($xml), 'yellow')." : ".colorize('sent to XMPP', 'green')."\n");
  64. }
  65. }
  66. } else {
  67. $buffer .= $data;
  68. }
  69. };
  70. $xmpp_behaviour = function (React\Stream\Stream $stream) use (&$conn, $loop, &$stdin, $stdin_behaviour, $parser) {
  71. $conn = $stream;
  72. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize('linker launched', 'blue')."\n");
  73. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." launched : ".\sizeToCleanSize(memory_get_usage())."\n");
  74. $stdin->removeAllListeners('data');
  75. $stdin->on('data', $stdin_behaviour);
  76. // We define a huge buffer to prevent issues with SSL streams, see https://bugs.php.net/bug.php?id=65137
  77. $conn->bufferSize = 1024*32;
  78. $conn->on('data', function($message) use (&$conn, $loop, $parser) {
  79. if(!empty($message)) {
  80. $restart = false;
  81. if($message == '</stream:stream>') {
  82. $conn->close();
  83. $loop->stop();
  84. } elseif($message == "<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
  85. || $message == '<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>') {
  86. $session = \Sessionx::start();
  87. stream_set_blocking($conn->stream, 1);
  88. stream_context_set_option($conn->stream, 'ssl', 'SNI_enabled', false);
  89. stream_context_set_option($conn->stream, 'ssl', 'peer_name', $session->host);
  90. stream_context_set_option($conn->stream, 'ssl', 'allow_self_signed', true);
  91. #stream_context_set_option($conn->stream, 'ssl', 'verify_peer_name', false);
  92. #stream_context_set_option($conn->stream, 'ssl', 'verify_peer', false);
  93. set_error_handler('handleSSLErrors');
  94. $out = stream_socket_enable_crypto($conn->stream, 1, STREAM_CRYPTO_METHOD_TLS_CLIENT);
  95. restore_error_handler();
  96. if($out !== true) {
  97. $loop->stop();
  98. return;
  99. }
  100. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize('TLS enabled', 'blue')."\n");
  101. $restart = true;
  102. }
  103. #fwrite(STDERR, colorize($message, 'yellow')." : ".colorize('received', 'green')."\n");
  104. #fwrite(STDERR, colorize(getenv('sid'), 'yellow')." widgets : ".\sizeToCleanSize(memory_get_usage())."\n");
  105. \Moxl\API::clear();
  106. \RPC::clear();
  107. if(!$parser->parse($message)) {
  108. fwrite(STDERR, colorize(getenv('sid'), 'yellow')." ".$parser->getError()."\n");
  109. }
  110. if($restart) {
  111. $session = \Sessionx::start();
  112. \Moxl\Stanza\Stream::init($session->host);
  113. stream_set_blocking($conn->stream, 0);
  114. $restart = false;
  115. }
  116. $msg = \RPC::commit();
  117. if(!empty($msg)) {
  118. //echo json_encode($msg)."";
  119. echo base64_encode(gzcompress(json_encode($msg), 9))."";
  120. //fwrite(STDERR, colorize(json_encode($msg).' '.strlen($msg), 'yellow')." : ".colorize('sent to browser', 'green')."\n");
  121. }
  122. \RPC::clear();
  123. $xml = \Moxl\API::commit();
  124. if(!empty($xml)) {
  125. $conn->write(trim($xml));
  126. #fwrite(STDERR, colorize(trim($xml), 'yellow')." : ".colorize('sent to XMPP', 'green')."\n");
  127. }
  128. \Moxl\API::clear();
  129. $loop->tick();
  130. gc_collect_cycles();
  131. //fwrite(STDERR, colorize(getenv('sid'), 'yellow')." end data : ".\sizeToCleanSize(memory_get_usage())."\n");
  132. //memprof_dump_callgrind(fopen("/tmp/callgrind.out", "w"));
  133. }
  134. });
  135. $conn->on('error', function($msg) use ($conn, $loop) {
  136. #fwrite(STDERR, colorize(serialize($msg), 'red')." : ".colorize('error', 'green')."\n");
  137. $loop->stop();
  138. });
  139. $conn->on('close', function($msg) use ($conn, $loop) {
  140. #fwrite(STDERR, colorize(serialize($msg), 'red')." : ".colorize('closed', 'green')."\n");
  141. $loop->stop();
  142. });
  143. // And we say that we are ready !
  144. $obj = new \StdClass;
  145. $obj->func = 'registered';
  146. fwrite(STDERR, 'registered');
  147. //fwrite(STDERR, colorize(json_encode($obj).' '.strlen($obj), 'yellow')." : ".colorize('obj sent to browser', 'green')."\n");
  148. echo base64_encode(gzcompress(json_encode($obj), 9))."";
  149. };
  150. $stdin->on('data', $stdin_behaviour);
  151. $stdin->on('error', function() use($loop) { $loop->stop(); } );
  152. $stdin->on('close', function() use($loop) { $loop->stop(); } );
  153. $loop->run();