php-mqtt/client

Writing large string error

giuseppedevito opened this issue · 2 comments

I think there is a bug at line 1150 of MqttClient class:

client/src/MqttClient.php

Lines 1141 to 1171 in 0847abe

protected function writeToSocket(string $data, int $length = null): void
{
$calculatedLength = strlen($data);
$length = min($length ?? $calculatedLength, $calculatedLength);
if ($this->settings->shouldUseBlockingSocket()) {
socket_set_blocking($this->socket, true);
}
$result = @fwrite($this->socket, $data, $length);
if ($this->settings->shouldUseBlockingSocket()) {
socket_set_blocking($this->socket, false);
}
if ($result === false || $result !== $length) {
$this->logger->error('Sending data over the socket to the broker failed.');
throw new DataTransferException(
DataTransferException::EXCEPTION_TX_DATA,
'Sending data over the socket failed. Has it been closed?'
);
}
$this->bytesSent += $length;
$this->logger->debug('Sent data over the socket: {data}', ['data' => $data]);
// After writing successfully to the socket, the broker should have received a new message from us.
// Because we only need to send a ping if no other messages are delivered, we can safely reset the ping timer.
$this->lastPingAt = microtime(true);
}

This will result in DataTransferException event with messages over 100 KB (MQTT has a maximum allowed message size of 256 MB).

I solved the issue adding the method:

protected function writeChunks($fp, $string) {
    $fwrite = 0;
    for ($written = 0; $written < strlen($string); $written += $fwrite) {
        $fwrite = @fwrite($fp, substr($string, $written));
        if ($fwrite === false) {
            return $written;
        }
    }
    return $written;
}

and changing line 1150 to:

$result = $this->writeChunks($this->socket, $data);

With this update your code is working fine.

A detailed analysis and a possible solution regarding this issue can be found in #133.

Tanks for your fast reply @Namoshek ... #133 closes this issue.