src/Protocol/Base/ReadPacketBuffer.php
public function getPacketIfExists()
    {
        $result = null;
        $ne = 0;
        // проверка пакетов с тайм-аутом
        foreach ($this->meta as $packetId => &$data) {
            if ($this->buffer[$packetId] !== false) {
                continue;
            }
            $ne++;
            if ($data['time'] < time() - self::READ_TIMEOUT) {
                // устанавливаем количество попыток
                if (isset($data['try'])) {
                    if ($data['try'] > 10) {
                        // если за 10 попыток не удалось получить пакет
                        // помечаем пакет как удалённый
                        $data['deleted'] = true;
                        throw new ReadException(
                            'Could not receive data packet with id ' . $packetId,
                            ReadException::ERROR_PROTOCOL
                        );
                    }
                    $data['try']++;
                } else {
                    $data['try'] = 1;
                }

                // дёргаем обработчик для отправки запроса пакета
                $this->eventRequestPacket->call($packetId);
                usleep(1000);

                // обновляем время последнего запроса пакета
                $data['time'] = time();
            } else {
                break;
            }
            unset($data);
        }
        if ($ne > 0) {

//            echo 'not enough', $ne, PHP_EOL;
        }

        $nextId = $this->lastCompletedId + 1;
        if (array_key_exists($nextId, $this->buffer) && $this->buffer[$nextId] !== false) {
            // если можно прочитать следующий по порядку пакет
            if ($this->meta[$nextId]['part']) {
                // если пакет является частью
                // пройдёмся по буферу и выясним, есть ли все части идущие за этим пакетом
                for ($i = $nextId + 1; array_key_exists($i, $this->buffer); $i++) {
                    if (
                        $this->buffer[$i] === false
                    ) {
                        // если пакет на текущей итерации ещё не получен,
                        // то дальнейшие поиски бессмысленны, выходим из цикла
                        break;
                    } elseif ($this->meta[$i]['part'] && $this->meta[$i]['end']) {
                        // если наткнулись на последний частичный пакет, значит до этого момента пакеты были частями
                        // собереём их по порядку, и выйдем из цикла вернув результат - собранный пакет
                        $packet = '';
                        $meta = $this->meta[$nextId]['meta'];
                        for ($j = $nextId; $j <= $i; $j++) {
                            $packet .= $this->buffer[$j];
                            unset($this->buffer[$j]);
                            unset($this->meta[$j]);
                        }
                        // установим id успешно прочитанного последнего пакета-части
                        $this->lastCompletedId = $i;
                        $result = [$packet, $meta];
                        break;
                    } else {
                    }
                }
            } else {
                // если пакет нормальный и готов к чтению
                $result = [$this->buffer[$nextId], $this->meta[$nextId]['meta']];
                unset($this->buffer[$nextId]);
                unset($this->meta[$nextId]);
                $this->lastCompletedId = $nextId;
            }
        }
        return $result;
    }
public function getPacketIfExists()
    {
        $result = null;
        $ne = 0;
        // проверка пакетов с тайм-аутом
        foreach ($this->meta as $packetId => &$data) {
            if ($this->buffer[$packetId] !== false) {
                continue;
            }
            $ne++;
            if ($data['time'] < time() - self::READ_TIMEOUT) {
                // устанавливаем количество попыток
                if (isset($data['try'])) {
                    if ($data['try'] > 10) {
                        // если за 10 попыток не удалось получить пакет
                        // помечаем пакет как удалённый
                        $data['deleted'] = true;
                        throw new ReadException(
                            'Could not receive data packet with id ' . $packetId,
                            ReadException::ERROR_PROTOCOL
                        );
                    }
                    $data['try']++;
                } else {
                    $data['try'] = 1;
                }

                // дёргаем обработчик для отправки запроса пакета
                $this->eventRequestPacket->call($packetId);
                usleep(1000);

                // обновляем время последнего запроса пакета
                $data['time'] = time();
            } else {
                break;
            }
            unset($data);
        }
        if ($ne > 0) {

//            echo 'not enough', $ne, PHP_EOL;
        }

        $nextId = $this->lastCompletedId + 1;
        if (array_key_exists($nextId, $this->buffer) && $this->buffer[$nextId] !== false) {
            // если можно прочитать следующий по порядку пакет
            if ($this->meta[$nextId]['part']) {
                // если пакет является частью
                // пройдёмся по буферу и выясним, есть ли все части идущие за этим пакетом
                for ($i = $nextId + 1; array_key_exists($i, $this->buffer); $i++) {
                    if (
                        $this->buffer[$i] === false
                    ) {
                        // если пакет на текущей итерации ещё не получен,
                        // то дальнейшие поиски бессмысленны, выходим из цикла
                        break;
                    } elseif ($this->meta[$i]['part'] && $this->meta[$i]['end']) {
                        // если наткнулись на последний частичный пакет, значит до этого момента пакеты были частями
                        // собереём их по порядку, и выйдем из цикла вернув результат - собранный пакет
                        $packet = '';
                        $meta = $this->meta[$nextId]['meta'];
                        for ($j = $nextId; $j <= $i; $j++) {
                            $packet .= $this->buffer[$j];
                            unset($this->buffer[$j]);
                            unset($this->meta[$j]);
                        }
                        // установим id успешно прочитанного последнего пакета-части
                        $this->lastCompletedId = $i;
                        $result = [$packet, $meta];
                        break;
                    } else {
                    }
                }
            } else {
                // если пакет нормальный и готов к чтению
                $result = [$this->buffer[$nextId], $this->meta[$nextId]['meta']];
                unset($this->buffer[$nextId]);
                unset($this->meta[$nextId]);
                $this->lastCompletedId = $nextId;
            }
        }
        return $result;
    }
Читает пакет из буфера.
Метод вернёт null если читать нечего.
Вернёт массив с данными пакета и его мета информацией:
['data', 'meta']

@return array|null
@throws \Exception