PHPPM\ProcessManager::onWeb PHP Метод

onWeb() публичный Метод

Handles incoming connections from $this->port. Basically redirects to a slave.
public onWeb ( Connection $incoming )
$incoming React\Socket\Connection 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);
    }