Method to start an asynchronous read for the first response message on
this exchange. It must be only called once per request/response. This
contains the logic to handle request verification, read-ahead handling,
etc.

@return VirtualConnection
977113
protected VirtualConnection startResponseRead() {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
            Tr.entry(tc, "startResponseRead");
        }
        HttpInvalidMessageException inv = checkRequestValidity();
        if (null != inv) {
            getAppWriteCallback().error(getVC(), inv);
            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
                Tr.exit(tc, "startResponseRead: error");
            }
            return null;
        }
        // check whether read-ahead is enabled. Bypass this code once the
        // init() method has been called (d264854) and continue as normal
        if (isReadAheadEnabled() && READ_STATE_TIME_RESET != getReadState()) {
            // read ahead is active

            int state = CALLBACK_STATE_IDLE;
            // grab the read-ahead states in a sync block to avoid timing windows
            // with the callback kicking in at the same time
            synchronized (this.stateSyncObject) {
                state = getCallbackState();
                setReadState(READ_STATE_ASYNC);
            }

            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                Tr.debug(tc, "Async response read, callback state: " + state);
            }
            switch (state) {
                case (CALLBACK_STATE_COMPLETE):
                    // read-ahead has already completed successfully, start the
                    // parse logic now
                    readAsyncResponse();
                    break;
                case (CALLBACK_STATE_ERROR):
                    // read-ahead already hit an error, trigger that path now
                    setPersistent(false);
                    reConnect(getVC(), this.readException);
                    break;
                case (CALLBACK_STATE_PENDING):
                    // read-ahead is still going on
                    break;
                default:
                    if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                        Tr.debug(tc, "Unexpected state (" + state + ") during async readahead");
                    }
                    setPersistent(false);
                    reConnect(getVC(), new IOException("Read-ahead state failure"));
                    break;
            }
            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
                Tr.exit(tc, "startResponseRead: read-ahead");
            }
            return null;
        }

        // When we get here, then the final write of the request has finished
        // and we need to tell the app channel of that IF the temp response
        // reads have been triggered. We will not read for a response here as
        // the app channel is using readNextResponse() for that path.
        // LI4335 - early reads also avoid starting read here
        if (this.bEarlyReads || this.bTempResponsesUsed) {
            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
                Tr.exit(tc, "startResponseRead: temp resp env");
            }
            getAppWriteCallback().complete(getVC());
            return null;
        }

        // otherwise start the read for the response now...
        getResponseImpl();
        readAsyncResponse();

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
            Tr.exit(tc, "startResponseRead");
        }
        return null;
    }
150804
public function onSessionReadEvent()
    {
        return function ($sessionEvent) {
            /** @var \PHPDaemon\Core\DeferredEvent $sessionEvent */
            $name = ini_get('session.name');
            $sid = $this->getCookieStr($name);
            if ($sid === '') {
                $sessionEvent->setResult(false);
                return;
            }
            if ($this->getSessionState() !== null) {
                $sessionEvent->setResult(true);
                return;
            }
            $this->sessionRead($sid, function ($data) use ($sessionEvent, $sid) {
                $canDecode = $data !== false && $this->sessionDecode($data);
                $sessionEvent->setResult($canDecode);
            });
        };
    }
1221753
public function receiveNoWait()
    {
        if ($this->currentEnvelope) {
            throw new \RuntimeException(
                'AmqpQueueDriver: This driver has a message that was not acknowledged yet. A message must be processed and acknowledged before receiving new messages.'
            );
        }

        $this->dequeueingTimeMs = 0;

        $this->currentEnvelope = $this->queue->get();

        $msg = null;

        if (!$this->currentEnvelope) {
            return null;
        }

        $start = microtime(true);
        $deserializationContext = new DeserializationContext();

        /** @var QueueMessageInterface $msg */
        $msg = $this->getSerializer()->deserialize($this->currentEnvelope->getBody(), SerializableInterface::class, $this->format, $deserializationContext);

        foreach ($this->currentEnvelope->getHeaders() as $header => $value) {
            $msg->setHeader($header, $value);
        }

        // Calculate how long it took to deserilize the message
        $this->dequeueingTimeMs = (int) ((microtime(true) - $start) * 1000);

        return $msg;
    }
975348
public function getConnection()
    {
        try {
            if ($this->instancia == null) {

                $json = new JsonReader(BASE_DIR . self::PATH_CONFIG_FILE);

                if (!empty(glob(dirname(__DIR__, 4) . self::PATH_CONFIG_FILE )[0])) {
                    $json = new JsonReader(glob(dirname(__DIR__, 4) . PATH_CONFIG_FILE)[0]);
                }

                $json= $json->read();
                try {

                    $connectionCache = $json->phiber->link->connection_cache == 1 ? true : false;

                    $this->instancia = new PDO(
                        $json->phiber->link->url,
                        $json->phiber->link->user,
                        $json->phiber->link->password,
                        array(
                            PDO::ATTR_PERSISTENT => $connectionCache
                        )
                    );
                } catch (PhiberException $e) {
                    throw new PhiberException(new Internationalization("database_connection_error"));
                }
            }

            return $this->instancia;

        } catch (PhiberException $e) {
            throw new PhiberException(new Internationalization("database_connection_error"));
        }
    }
1118466
public function onRead()
    {
        start:
        if ($this->state === self::STATE_ROOT) {
            $header = $this->readExact(8);

            if ($header === false) {
                return;
            }

            $this->header = unpack('Cver/Ctype/nreqid/nconlen/Cpadlen/Creserved', $header);

            if ($this->header['conlen'] > 0) {
                $this->setWatermark($this->header['conlen'], $this->header['conlen']);
            }
            $type = $this->header['type'];
            $this->header['ttype'] = isset(self::$requestTypes[$type]) ? self::$requestTypes[$type] : $type;
            $rid = $this->header['reqid'];
            $this->state = self::STATE_CONTENT;
        } else {
            $type = $this->header['type'];
            $rid = $this->header['reqid'];
        }
        if ($this->state === self::STATE_CONTENT) {
            $this->content = $this->readExact($this->header['conlen']);

            if ($this->content === false) {
                $this->setWatermark($this->header['conlen'], $this->header['conlen']);
                return;
            }

            if ($this->header['padlen'] > 0) {
                $this->setWatermark($this->header['padlen'], $this->header['padlen']);
            }

            $this->state = self::STATE_PADDING;
        }

        if ($this->state === self::STATE_PADDING) {
            $pad = $this->readExact($this->header['padlen']);

            if ($pad === false) {
                return;
            }
        }
        $this->setWatermark(8, 0xFFFFFF);
        $this->state = self::STATE_ROOT;

//        /*Daemon::log('[DEBUG] FastCGI-record ' . $this->header['ttype'] . '). Request ID: ' . $rid
//                . '. Content length: ' . $this->header['conlen'] . ' (' . mb_orig_strlen($this->content) . ') Padding length: ' . $this->header['padlen']
//                . ' (' . mb_orig_strlen($pad) . ')');*/

        if ($type === self::FCGI_BEGIN_REQUEST) {
            $u = unpack('nrole/Cflags', $this->content);

            $req = new \stdClass();
            $req->attrs = new \stdClass;
            $req->attrs->request = [];
            $req->attrs->get = [];
            $req->attrs->post = [];
            $req->attrs->cookie = [];
            $req->attrs->server = [];
            $req->attrs->files = [];
            $req->attrs->session = null;
            $req->attrs->role = self::$roles[$u['role']];
            $req->attrs->flags = $u['flags'];
            $req->attrs->id = $this->header['reqid'];
            $req->attrs->paramsDone = false;
            $req->attrs->inputDone = false;
            $req->attrs->input = new \PHPDaemon\HTTPRequest\Input();
            $req->attrs->chunked = false;
            $req->attrs->noHttpVer = true;
            $req->queueId = $rid;
            $this->requests[$rid] = $req;
        } elseif (isset($this->requests[$rid])) {
            $req = $this->requests[$rid];
        } else {
            Daemon::log('Unexpected FastCGI-record #' . $this->header['type'] . ' (' . $this->header['ttype'] . '). Request ID: ' . $rid . '.');
            return;
        }

        if ($type === self::FCGI_ABORT_REQUEST) {
            $req->abort();
        } elseif ($type === self::FCGI_PARAMS) {
            if ($this->content === '') {
                if (!isset($req->attrs->server['REQUEST_TIME'])) {
                    $req->attrs->server['REQUEST_TIME'] = time();
                }
                if (!isset($req->attrs->server['REQUEST_TIME_FLOAT'])) {
                    $req->attrs->server['REQUEST_TIME_FLOAT'] = microtime(true);
                }
                $req->attrs->paramsDone = true;

                $req = Daemon::$appResolver->getRequest($req, $this);

                if ($req instanceof \stdClass) {
                    $this->endRequest($req, 0, 0);
                    unset($this->requests[$rid]);
                } else {
                    if ($this->pool->config->sendfile->value
                        && (
                            !$this->pool->config->sendfileonlybycommand->value
                            || isset($req->attrs->server['USE_SENDFILE'])
                        )
                        && !isset($req->attrs->server['DONT_USE_SENDFILE'])
                    ) {
                        $fn = tempnam(
                            $this->pool->config->sendfiledir->value,
                            $this->pool->config->sendfileprefix->value
                        );

                        $req->sendfp = fopen($fn, 'wb');
                        $req->header('X-Sendfile: ' . $fn);
                    }

                    $this->requests[$rid] = $req;

                    $req->callInit();
                }
            } else {
                $p = 0;

                while ($p < $this->header['conlen']) {
                    if (($namelen = ord($this->content{$p})) < 128) {
                        ++$p;
                    } else {
                        $u = unpack(
                            'Nlen',
                            chr(ord($this->content{$p}) & 0x7f) . mb_orig_substr($this->content, $p + 1, 3)
                        );
                        $namelen = $u['len'];
                        $p += 4;
                    }

                    if (($vlen = ord($this->content{$p})) < 128) {
                        ++$p;
                    } else {
                        $u = unpack(
                            'Nlen',
                            chr(ord($this->content{$p}) & 0x7f) . mb_orig_substr($this->content, $p + 1, 3)
                        );
                        $vlen = $u['len'];
                        $p += 4;
                    }

                    $req->attrs->server[mb_orig_substr($this->content, $p, $namelen)] = mb_orig_substr(
                        $this->content,
                        $p + $namelen,
                        $vlen
                    );
                    $p += $namelen + $vlen;
                }
            }
        } elseif ($type === self::FCGI_STDIN) {
            if (!$req->attrs->input) {
                goto start;
            }
            if ($this->content === '') {
                $req->attrs->input->sendEOF();
            } else {
                $req->attrs->input->readFromString($this->content);
            }
        }

        if ($req->attrs->inputDone && $req->attrs->paramsDone) {
            $order = $this->pool->variablesOrder ?: 'GPC';
            for ($i = 0, $s = mb_orig_strlen($order); $i < $s; ++$i) {
                $char = $order[$i];

                if ($char === 'G' && is_array($req->attrs->get)) {
                    $req->attrs->request += $req->attrs->get;
                } elseif ($char === 'P' && is_array($req->attrs->post)) {
                    $req->attrs->request += $req->attrs->post;
                } elseif ($char === 'C' && is_array($req->attrs->cookie)) {
                    $req->attrs->request += $req->attrs->cookie;
                }
            }

            Daemon::$process->timeLastActivity = time();
        }
        goto start;
    }
471460
public function first()
    {
        try {
            $query = (clone $this)->limit(1)->apply($this->database->getTablePrefixer());
            $compiled = $this->database->getGrammar()->compileSelect($query);
            return $this->database->selectFirst($compiled->getSQL(), $compiled->getBindings());
        } catch (\Throwable $exception) {
            return $this->handleException($exception);
        }
    }
1349518
public function connect()
    {
        if ($this->connection->isConnected() && !empty($this->hello)) {
            return $this->hello;
        }

        $this->connectToTheNode();
        $this->authenticateWithPassword();

        try {
            $this->sayHello();
        } catch (ResponseException $e) {
            /**
             * If the node requires a password but we didn't supply any,
             * Disque returns a message "NOAUTH Authentication required"
             *
             * HELLO is the first place we would get this error.
             *
             * @see https://github.com/antirez/disque/blob/master/src/server.c
             * Look for "noautherr"
             */
            $message = $e->getMessage();
            if (stripos($message, self::AUTH_REQUIRED_MESSAGE) === 0) {
                throw new AuthenticationException($message, 0, $e);
            }
        }

        return $this->hello;
    }
778739
public function build(): ReadRequest
	{
		$instance = new ReadRequest();
		if ($this->handle === null) {
			throw new BuilderException('Property [handle] is required.');
		}
		$instance->handle = $this->handle;
		$instance->offset = $this->offset;
		$instance->size = $this->size;
		return $instance;
	}
374878
public function read()
    {
        // First, read headers only
        $response = '';
        $gotStatus = false;
        while (($line = @fgets($this->socket)) !== false) {
            $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
            if ($gotStatus) {
                $response .= $line;
                if (rtrim($line) === '') break;
            }
        }

        $statusCode = Zend_Http_Response::extractCode($response);

        // Handle 100 and 101 responses internally by restarting the read again
        if ($statusCode == 100 || $statusCode == 101) return $this->read();

        /**
         * Responses to HEAD requests and 204 or 304 responses are not expected
         * to have a body - stop reading here
         */
        if ($statusCode == 304 || $statusCode == 204 ||
            $this->method == Zend_Http_Client::HEAD) return $response;

        // Check headers to see what kind of connection / transfer encoding we have
        $headers = Zend_Http_Response::extractHeaders($response);

        // If we got a 'transfer-encoding: chunked' header
        if (isset($headers['transfer-encoding'])) {
            if ($headers['transfer-encoding'] == 'chunked') {
                do {
                    $line  = @fgets($this->socket);
                    $chunk = $line;

                    // Figure out the next chunk size
                    $chunksize = trim($line);
                    if (! ctype_xdigit($chunksize)) {
                        $this->close();
                        require_once 'Zend/Http/Client/Adapter/Exception.php';
                        throw new Zend_Http_Client_Adapter_Exception('Invalid chunk size "' .
                            $chunksize . '" unable to read chunked body');
                    }

                    // Convert the hexadecimal value to plain integer
                    $chunksize = hexdec($chunksize);

                    // Read chunk
                    $left_to_read = $chunksize;
                    while ($left_to_read > 0) {
                        $line = @fread($this->socket, $left_to_read);
                        if ($line === false || strlen($line) === 0)
                        {
                            break;
                        } else {
                            $chunk .= $line;
                            $left_to_read -= strlen($line);
                        }

                        // Break if the connection ended prematurely
                        if (feof($this->socket)) break;
                    }

                    $chunk .= @fgets($this->socket);
                    $response .= $chunk;
                } while ($chunksize > 0);

            } else {
                throw new Zend_Http_Client_Adapter_Exception('Cannot handle "' .
                    $headers['transfer-encoding'] . '" transfer encoding');
            }

        // Else, if we got the content-length header, read this number of bytes
        } elseif (isset($headers['content-length'])) {
            $left_to_read = $headers['content-length'];
            $chunk = '';
            while ($left_to_read > 0) {
                $chunk = @fread($this->socket, $left_to_read);
                if ($chunk === false || strlen($chunk) === 0)
                {
                    break;
                } else {
                    $left_to_read -= strlen($chunk);
                    $response .= $chunk;
                }

                // Break if the connection ended prematurely
                if (feof($this->socket)) break;
            }

        // Fallback: just read the response until EOF
        } else {
        	do {
        		$buff = @fread($this->socket, 8192);
        		if ($buff === false || strlen($buff) === 0)
        		{
        			break;
        		} else {
                    $response .= $buff;
        		}
        	} while (feof($this->socket) === false);

            $this->close();
        }

        // Close the connection if requested to do so by the server
        if (isset($headers['connection']) && $headers['connection'] == 'close') {
            $this->close();
        }

        return $response;
    }
938337
private function addNextRequest()
    {
        add_next:

        if ($this->isRealized || !$this->iter || !$this->iter->valid()) {
            return false;
        }

        $request = $this->iter->current();
        $this->iter->next();

        if (!($request instanceof RequestInterface)) {
            throw new \InvalidArgumentException(sprintf(
                'All requests in the provided iterator must implement '
                . 'RequestInterface. Found %s',
                Core::describeType($request)
            ));
        }

        // Be sure to use "lazy" futures, meaning they do not send right away.
        $request->getConfig()->set('future', 'lazy');
        $hash = spl_object_hash($request);
        $this->attachListeners($request, $this->eventListeners);
        $request->getEmitter()->on('before', [$this, '_trackRetries'], RequestEvents::EARLY);
        $response = $this->client->send($request);
        $this->waitQueue[$hash] = $response;
        $promise = $response->promise();

        // Don't recursively call itself for completed or rejected responses.
        if ($promise instanceof FulfilledPromise
            || $promise instanceof RejectedPromise
        ) {
            try {
                $this->finishResponse($request, $response->wait(), $hash);
            } catch (\Exception $e) {
                $this->finishResponse($request, $e, $hash);
            }
            goto add_next;
        }

        // Use this function for both resolution and rejection.
        $thenFn = function ($value) use ($request, $hash) {
            $this->finishResponse($request, $value, $hash);
            if (!$request->getConfig()->get('_pool_retries')) {
                $this->addNextRequests();
            }
        };

        $promise->then($thenFn, $thenFn);

        return true;
    }
693738
public function receive(): Promise
    {
        if ($this->reader) {
            throw new PendingReceiveError;
        }

        if (!$this->socket) {
            return new Success; // Resolve with null when endpoint is closed.
        }

        $this->reader = new Deferred;
        Loop::enable($this->watcher);

        return $this->reader->promise();
    }
150554
public function onReady()
    {
        $appInstance = $this; // a reference to this application instance for ExampleWebSocketRoute
        // URI /exampleApp should be handled by ExampleWebSocketRoute
        \PHPDaemon\Servers\WebSocket\Pool::getInstance()->addRoute('exampleApp', function ($client) use ($appInstance) {
            return new ExampleWebSocketRoute($client, $appInstance);
        });
    }
878036
protected function executeNextWaitingRequest()
    {
        if (($this->numberOfParallelRequests === 0 || count($this->runningRequests) < $this->numberOfParallelRequests)
            && count($this->waitingRequests) > 0
        ) {
            $this->executeRequest(reset($this->waitingRequests));
        }
        return $this;
    }
879358
public function onRead()
    {
        $packet = $this->read(1024);
        $orig = $packet;
        $type = Binary::getByte($packet);
        $code = Binary::getByte($packet);
        $checksum = Binary::getStrWord($packet);
        $id = Binary::getWord($packet);
        $seq = Binary::getWord($packet);
        if ($checksum !== self::checksum(substr_replace($orig, "\x00\x00", 2, 2))) {
            $status = 'badChecksum';
        } elseif ($type === 0x03) {
            $status = isset(static::$unreachableCodes[$code]) ? static::$unreachableCodes[$code] : 'unk' . $code . 'unreachable';
        } else {
            $status = 'unknownType0x' . dechex($type);
        }
        while (!$this->onResponse->isEmpty()) {
            $el = $this->onResponse->shift();
            if ($el instanceof CallbackWrapper) {
                $el = $el->unwrap();
            }
            list($cb, $st) = $el;
            $cb(microtime(true) - $st, $status);
        }
        $this->finish();
    }
1330836
public function runAction()
    {
        $args = $this->getRequest()->getArgv();
        if (!isset($args[2], $args[3])) {
            return $this->help('run');
        }
        $request = new VirtualRequest($args[2], $args[3]);
        $response = $this->dispatch($request);
        if ($response->getCode() !== 200) {
            $response->setContent("Wrong arguments provided\n");
        }

        return $response;
    }
1026155
protected function connect()
    {
        try {
            // Loop until we connect
            while (!$this->isConnected()) {
                // Assume we will connect, until we dont
                $this->setIsConnected(true);

                // Connect the socket
                $this->io->connect();

                $this->channels = array();
                // The connection object itself is treated as channel 0
                parent::__construct($this, 0);

                $this->input = new AMQPReader(null, $this->io);

                $this->write($this->amqp_protocol_header);
                $this->wait(array($this->waitHelper->get_wait('connection.start')),false,$this->connection_timeout);
                $this->x_start_ok(
                    $this->getLibraryProperties(),
                    $this->login_method,
                    $this->login_response,
                    $this->locale
                );

                $this->wait_tune_ok = true;
                while ($this->wait_tune_ok) {
                    $this->wait(array(
                        $this->waitHelper->get_wait('connection.secure'),
                        $this->waitHelper->get_wait('connection.tune')
                    ));
                }

                $host = $this->x_open($this->vhost, '', $this->insist);
                if (!$host) {
                    //Reconnected
                    $this->io->reenableHeartbeat();
                    return null; // we weren't redirected
                }

                $this->setIsConnected(false);
                $this->closeChannels();

                // we were redirected, close the socket, loop and try again
                $this->close_socket();
            }

        } catch (\Exception $e) {
            // Something went wrong, set the connection status
            $this->setIsConnected(false);
            $this->closeChannels();
            $this->close_input();
            $this->close_socket();
            throw $e; // Rethrow exception
        }
    }
1347879
public VirtualConnection read(UDPReadCompletedCallback callback, boolean forceQueue) {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
            Tr.entry(tc, "read(force=" + forceQueue + ")");
        }

        this.readCallback = callback;
        this.readCalled = true;
        this.bIsForceQueue = forceQueue;

        VirtualConnection vc = getWorkQueueManager().processWork(this);

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
            Tr.exit(tc, "read(): " + vc);
        }

        return vc;
    }