Inheritance: extends Evenement\EventEmitter, implements React\Socket\ConnectionInterface
コード例 #1
0
 private function acquireCommand(React\Socket\Connection $connection, $name)
 {
     if (isset($this->locks[$name])) {
         if (isset($this->connections[$connection][$name])) {
             if ($this->connections[$connection][$name]) {
                 $connection->write(self::SUCCESS);
                 return;
             } else {
                 $connection->write(self::WAIT);
                 return;
             }
         } else {
             $this->locks[$name][] = $connection;
             $connectionLocks = $this->connections[$connection];
             $connectionLocks[$name] = false;
             $this->connections[$connection] = $connectionLocks;
             $connection->write(self::WAIT);
             return;
         }
     } else {
         $this->locks[$name] = new \SplDoublyLinkedList();
         $this->locks[$name][] = $connection;
         $connectionLocks = $this->connections[$connection];
         $connectionLocks[$name] = true;
         $this->connections[$connection] = $connectionLocks;
         $connection->write(self::SUCCESS);
         return;
     }
 }
コード例 #2
0
 /**
  * Handle process on close transport
  *
  * @param \React\Socket\Connection $conn
  */
 public function handleClose(Connection $conn)
 {
     Logger::debug($this, "Raw socket closed " . $conn->getRemoteAddress());
     $session = $this->sessions[$conn];
     $this->sessions->detach($conn);
     $this->router->getEventDispatcher()->dispatch('connection_close', new ConnectionCloseEvent($session));
 }
コード例 #3
0
ファイル: ConnectionTest.php プロジェクト: ramiyer/react
 /**
  * @covers React\Socket\Connection::end
  */
 public function testEnd()
 {
     $socket = fopen('php://temp', 'r+');
     $loop = $this->createLoopMock();
     $conn = new Connection($socket, $loop);
     $conn->end();
     $this->assertFalse(is_resource($socket));
 }
コード例 #4
0
ファイル: Client.php プロジェクト: php-pm/php-pm
 /**
  * @return Connection
  */
 protected function getConnection()
 {
     if ($this->connection) {
         $this->connection->close();
         unset($this->connection);
     }
     $client = stream_socket_client($this->getControllerSocket());
     $this->connection = new Connection($client, $this->loop);
     return $this->connection;
 }
コード例 #5
0
ファイル: Client.php プロジェクト: atiarda/php-pm
 /**
  * @return \React\Socket\Connection
  */
 protected function getConnection()
 {
     if ($this->connection) {
         $this->connection->close();
         unset($this->connection);
     }
     $client = stream_socket_client('tcp://127.0.0.1:5500');
     $this->connection = new \React\Socket\Connection($client, $this->loop);
     return $this->connection;
 }
コード例 #6
0
 public function accept(Socket $socket)
 {
     if (count($this->connections) >= $this->maxConnections) {
         $socket->write(['alias' => 'capacity_reached']);
         $socket->close();
         throw new \RuntimeException('Server capacity reached');
     }
     $player = $this->playerFactory->newSocketPlayer(sprintf('PlayerBot%d', ++$this->connectionIndex), null, 5000, $socket);
     $connection = $player->getConnection();
     $this->connections->pushBack($connection);
     $this->handleSocketEvents($connection);
     $this->handlePlayerNameChange($connection);
     $this->handlePlayerConnection($connection);
 }
コード例 #7
0
 /**
  * Disconnect from server
  */
 public function disconnect()
 {
     $this->connected = false;
     if ($this->socket instanceof Connection) {
         $this->socket->close();
     }
 }
コード例 #8
0
ファイル: ProcessSlave.php プロジェクト: php-pm/php-pm
 /**
  * Connects to ProcessManager, master process.
  */
 public function run()
 {
     $this->loop = \React\EventLoop\Factory::create();
     $this->errorLogger = BufferingLogger::create();
     ErrorHandler::register(new ErrorHandler($this->errorLogger));
     $client = stream_socket_client($this->config['controllerHost']);
     $this->controller = new \React\Socket\Connection($client, $this->loop);
     $pcntl = new \MKraemer\ReactPCNTL\PCNTL($this->loop);
     $pcntl->on(SIGTERM, [$this, 'shutdown']);
     $pcntl->on(SIGINT, [$this, 'shutdown']);
     register_shutdown_function([$this, 'shutdown']);
     $this->bindProcessMessage($this->controller);
     $this->controller->on('close', \Closure::bind(function () {
         $this->shutdown();
     }, $this));
     $this->server = new React\Server($this->loop);
     //our version for now, because of unix socket support
     $http = new HttpServer($this->server);
     $http->on('request', array($this, 'onRequest'));
     //port is only used for tcp connection. If unix socket, 'host' contains the socket path
     $port = $this->config['port'];
     $host = $this->config['host'];
     while (true) {
         try {
             $this->server->listen($port, $host);
             break;
         } catch (\React\Socket\ConnectionException $e) {
             usleep(500);
         }
     }
     $this->sendMessage($this->controller, 'register', ['pid' => getmypid(), 'port' => $port]);
     $this->loop->run();
 }
コード例 #9
0
ファイル: ProcessSlave.php プロジェクト: atiarda/php-pm
 public function bye()
 {
     if ($this->connection->isWritable()) {
         $this->connection->write(json_encode(array('cmd' => 'unregister', 'pid' => getmypid())));
         $this->connection->close();
     }
     $this->loop->stop();
 }
コード例 #10
0
ファイル: Controller.php プロジェクト: phxlol/lol-php-api
 /**
  * Apply revoked client connection listeners
  */
 protected function applyListeners()
 {
     foreach ($this->listeners as $listenerName => $listeners) {
         foreach ($listeners as $listener) {
             $this->conn->on('api-' . $listenerName, $listener);
         }
     }
     $this->listeners = [];
 }
コード例 #11
0
 public function handleData($stream)
 {
     if (!$this->secure) {
         //stream_set_blocking($this->stream, true);
         $result = stream_socket_enable_crypto($this->stream, true, STREAM_CRYPTO_METHOD_TLS_SERVER);
         //stream_set_blocking($this->stream, false);
         if (0 === $result) {
             return;
         }
         if (false === $result) {
             echo "error\n";
             return;
         }
         $this->secure = true;
         $this->emit('connection', array($this));
     }
     parent::handleData($stream);
 }
コード例 #12
0
ファイル: ProcessSlave.php プロジェクト: marcj/php-pm
 /**
  * Connects to ProcessManager, master process.
  */
 public function run()
 {
     $this->loop = \React\EventLoop\Factory::create();
     ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
     $this->client = stream_socket_client('tcp://127.0.0.1:5500');
     $this->connection = new \React\Socket\Connection($this->client, $this->loop);
     $this->connection->on('error', function ($data) {
         var_dump($data);
     });
     $pcntl = new \MKraemer\ReactPCNTL\PCNTL($this->loop);
     $pcntl->on(SIGTERM, [$this, 'shutdown']);
     $pcntl->on(SIGINT, [$this, 'shutdown']);
     register_shutdown_function([$this, 'shutdown']);
     $this->bindProcessMessage($this->connection);
     $this->connection->on('close', \Closure::bind(function () {
         $this->shutdown();
     }, $this));
     $this->server = new \React\Socket\Server($this->loop);
     $this->server->on('error', function ($data) {
         var_dump($data);
     });
     $http = new HttpServer($this->server);
     $http->on('request', array($this, 'onRequest'));
     $http->on('error', function ($data) {
         var_dump($data);
     });
     $port = $this->config['port'];
     while (true) {
         try {
             $this->server->listen($port);
             break;
         } catch (\React\Socket\ConnectionException $e) {
             usleep(500);
         }
     }
     $this->sendMessage($this->connection, 'register', ['pid' => getmypid(), 'port' => $port]);
     $this->loop->run();
 }
コード例 #13
0
ファイル: ProcessManager.php プロジェクト: ravismula/php-pm
 public function onSlaveConnection(\React\Socket\Connection $conn)
 {
     $conn->on('data', \Closure::bind(function ($data) use($conn) {
         $this->onData($data, $conn);
     }, $this));
     $conn->on('close', \Closure::bind(function () use($conn) {
         foreach ($this->slaves as $idx => $slave) {
             if ($slave['connection'] === $conn) {
                 unset($this->slaves[$idx]);
                 $this->checkSlaves();
             }
         }
     }, $this));
 }
コード例 #14
0
ファイル: ProcessManager.php プロジェクト: marcj/php-pm
 /**
  * A slave sent a `status` command.
  *
  * @param array $data
  * @param Connection $conn
  */
 protected function commandStatus(array $data, Connection $conn)
 {
     $conn->end(json_encode('todo'));
 }
コード例 #15
0
 /**
  * Sends a message through $conn.
  *
  * @param Connection $conn
  * @param string $command
  * @param array $message
  */
 protected function sendMessage(Connection $conn, $command, array $message = [])
 {
     $message['cmd'] = $command;
     $conn->write(json_encode($message) . PHP_EOL);
 }
コード例 #16
0
ファイル: client.php プロジェクト: greevex/react-easy-server
 /**
  * Disconnect client
  */
 public function disconnect()
 {
     $this->clientConnection->close();
 }
コード例 #17
0
ファイル: Client.php プロジェクト: j92/chattest
 public function __construct($connection, LoopInterface $loop, DatabaseAdapter $database)
 {
     $this->connection = $connection;
     $this->database = $database;
     parent::__construct($connection->stream, $loop);
 }
コード例 #18
0
 public function __construct($socket, LoopInterface $loop, $logger)
 {
     parent::__construct($socket, $loop);
     $this->_lastChanged = time();
     $this->logger = $logger;
 }
コード例 #19
0
ファイル: ProcessManager.php プロジェクト: php-pm/php-pm
 /**
  * Handles incoming connections from $this->port. Basically redirects to a slave.
  *
  * @param Connection $incoming incoming connection from react
  */
 public function onWeb(Connection $incoming)
 {
     //preload sent data from $incoming to $buffer, otherwise it would be lost,
     //since getNextSlave is async.
     $redirectionActive = false;
     $connectionOpen = true;
     $incomingBuffer = '';
     $incoming->on('data', function ($data) use(&$redirectionActive, &$incomingBuffer) {
         if (!$redirectionActive) {
             $incomingBuffer .= $data;
         }
     });
     $redirectionTries = 0;
     $incoming->on('close', function () use(&$redirectionActive, &$redirectionTries, &$connectionOpen) {
         $connectionOpen = false;
     });
     $start = microtime(true);
     $redirectionTries++;
     $redirectRequest = function ($id) use(&$redirectRequest, &$incoming, &$incomingBuffer, &$redirectionActive, $start, &$redirectionTries, &$connectionOpen) {
         if (!$connectionOpen) {
             //since the initial connection of a client and getting a free worker the client meanwhile closed the connection,
             //so stop anything here.
             return;
         }
         if (!is_resource($incoming->stream)) {
             //Firefox closes somehow a connection directly after opening, at this state we need to check
             //whether the connection is still alive, to keep going. This check prevents the server from crashing
             return;
         }
         $took = microtime(true) - $start;
         if ($this->output->isVeryVerbose() && $took > 1) {
             $this->output->writeln(sprintf('<info>took abnormal %f seconds for choosing next free worker</info>', $took));
         }
         $slave =& $this->slaves[$id];
         $slave['busy'] = true;
         $slave['connections']++;
         $start = microtime(true);
         $stream = stream_socket_client($slave['host'], $errno, $errstr, $this->timeout);
         if (!$stream || !is_resource($stream)) {
             //we failed to connect to the worker. Maybe because of timeouts or it is in a crashed state
             //and is currently dieing.
             //since we don't know whether the worker is only very busy or dieing we just
             //set it back to available worker list. If it is really dying it will be
             //removed from the available worker list by itself during connection:close event.
             $slave['busy'] = false;
             $slave['connections']--;
             if ($this->output->isVeryVerbose()) {
                 $this->output->writeln(sprintf('<error>Connection to worker %d failed. Try #%d, took %fs. ' . 'Try increasing your timeout of %d. Error message: [%d] %s</error>', $id, $redirectionTries, microtime(true) - $start, $this->timeout, $errno, $errstr));
             }
             //Try next free client. It's important to do this here due to $incomingBuffer.
             $redirectionTries++;
             $this->getNextSlave($redirectRequest);
             return;
         }
         $connection = new \React\Socket\Connection($stream, $this->loop);
         $took = microtime(true) - $start;
         if ($this->output->isVeryVerbose() && $took > 1) {
             $this->output->writeln(sprintf('<info>took abnormal %f seconds for connecting to :%d</info>', $took, $slave['port']));
         }
         $start = microtime(true);
         $headersToReplace = ['X-PHP-PM-Remote-IP' => $incoming->getRemoteAddress()];
         $headerRedirected = false;
         if ($this->isHeaderEnd($incomingBuffer)) {
             $incomingBuffer = $this->replaceHeader($incomingBuffer, $headersToReplace);
             $headerRedirected = true;
             $connection->write($incomingBuffer);
         }
         $redirectionActive = true;
         $connection->on('close', function () use($incoming, &$slave, $start) {
             $took = microtime(true) - $start;
             if ($this->output->isVeryVerbose() && $took > 1) {
                 $this->output->writeln(sprintf('<info>took abnormal %f seconds for handling a connection</info>', $took));
             }
             $slave['busy'] = false;
             $slave['connections']--;
             $slave['requests']++;
             $incoming->end();
             /** @var Connection $connection */
             $connection = $slave['connection'];
             if ($slave['requests'] >= $this->maxRequests) {
                 $slave['ready'] = false;
                 $this->output->writeln(sprintf('Restart worker #%d because it reached maxRequests of %d', $slave['port'], $this->maxRequests));
                 $connection->close();
             } else {
                 if ($slave['closeWhenFree']) {
                     $connection->close();
                 }
             }
         });
         $connection->on('data', function ($buffer) use($incoming) {
             $incoming->write($buffer);
         });
         $incoming->on('data', function ($buffer) use($connection, &$incomingBuffer, $headersToReplace, &$headerRedirected) {
             if (!$headerRedirected) {
                 $incomingBuffer .= $buffer;
                 if ($this->isHeaderEnd($incomingBuffer)) {
                     $incomingBuffer = $this->replaceHeader($incomingBuffer, $headersToReplace);
                     $headerRedirected = true;
                     $connection->write($incomingBuffer);
                 } else {
                     //head has not completely received yet, wait
                 }
             } else {
                 //incomingBuffer has already been redirected, so redirect now buffer per buffer
                 $connection->write($buffer);
             }
         });
         $incoming->on('close', function () use($connection) {
             $connection->close();
         });
     };
     $this->getNextSlave($redirectRequest);
 }
コード例 #20
0
ファイル: ProcessManager.php プロジェクト: php-pm/php-pm
 /**
  * A slave sent a `register` command.
  *
  * @param array      $data
  * @param Connection $conn
  */
 protected function commandRegister(array $data, Connection $conn)
 {
     $pid = (int) $data['pid'];
     $port = (int) $data['port'];
     if (!isset($this->slaves[$port]) || !$this->slaves[$port]['waitForRegister']) {
         if ($this->output->isVeryVerbose()) {
             $this->output->writeln(sprintf('<error>Worker #%d wanted to register on master which was not expected.</error>', $port));
         }
         $conn->close();
         return;
     }
     $this->ports[spl_object_hash($conn)] = $port;
     if ($this->output->isVeryVerbose()) {
         $this->output->writeln(sprintf('Worker #%d registered. Waiting for application bootstrap ... ', $port));
     }
     $this->slaves[$port]['pid'] = $pid;
     $this->slaves[$port]['connection'] = $conn;
     $this->slaves[$port]['ready'] = false;
     $this->slaves[$port]['waitForRegister'] = false;
     $this->slaves[$port]['duringBootstrap'] = true;
     $this->sendMessage($conn, 'bootstrap');
 }
コード例 #21
0
ファイル: ttt_server.php プロジェクト: phpCedu/ReactExamples
 protected function writeBoard()
 {
     $ui = Ui::printStatus($this->game);
     $this->connection->write($ui);
     echo $ui;
 }
コード例 #22
0
 protected function serve404Error(SocketConnection $conn)
 {
     $response = new Response('file not found.', Response::HTTP_NOT_FOUND);
     $conn->write($response);
     $conn->end();
 }
コード例 #23
0
 /**
  * Handle process on close transport
  *
  * @param \React\Socket\Connection $conn
  */
 public function handleClose(Connection $conn)
 {
     Logger::debug($this, "Raw socket closed " . $conn->getRemoteAddress());
     $transport = $this->transports[$conn];
     $this->transports->detach($conn);
     $this->peer->onClose($transport);
 }
コード例 #24
0
 /**
  * Disconnect from server
  */
 public function disconnect()
 {
     $this->connected = false;
     $this->socket->close();
 }
コード例 #25
0
 /**
  * Override the base end to add encryption if we're in an encypted stage
  *
  * @param $data String the data to write on ending
  * @Override
  */
 public function end($data = null)
 {
     //encrypt the data if needed
     if ($data !== null && $this->secret !== null) {
         mcrypt_generic_init($this->encryptor, $this->secret, $this->secret);
         $data = mcrypt_generic($this->encryptor, $data);
         mcrypt_generic_deinit($this->encryptor);
     }
     parent::end($data);
 }