diff --git a/src/Exception/ServerException.php b/src/Exception/ServerException.php index d323819..75a688e 100644 --- a/src/Exception/ServerException.php +++ b/src/Exception/ServerException.php @@ -24,6 +24,10 @@ public function __construct(array $error = [], ?Throwable $previous = null) { $code = $error['code'] ?? 0; $message = $error['message'] ?? 'Server Error'; + $class = $error['data']['class'] ?? ''; + if ($class) { + $message = $class . ': ' . $message; + } $this->error = $error; diff --git a/src/Transporter/MultiplexRpcTransporter.php b/src/Transporter/MultiplexRpcTransporter.php index 0d843bd..01d8e97 100644 --- a/src/Transporter/MultiplexRpcTransporter.php +++ b/src/Transporter/MultiplexRpcTransporter.php @@ -26,8 +26,12 @@ public function receive() { stream_set_blocking($this->client, false); + $remainingTimeout = $this->timeout; + $start = microtime(true); + while (true) { - $header = $this->readBytes(4); + $header = $this->readBytes(4, $remainingTimeout); + $remainingTimeout = max(0, $remainingTimeout - (microtime(true) - $start)); $unpacked = unpack('Nlength', $header); $length = $unpacked['length']; @@ -35,7 +39,9 @@ public function receive() if ($length < 4) { throw new RecvFailedException(sprintf('Invalid package length: %d', $length)); } - $body = $this->readBytes($length); + $body = $this->readBytes($length, $remainingTimeout); + $remainingTimeout = max(0, $remainingTimeout - (microtime(true) - $start)); + if (in_array($body, [self::PING, self::PONG], true)) { continue; } @@ -47,7 +53,7 @@ public function receive() /** * @throws Exception */ - private function readBytes(int $length): string + private function readBytes(int $length, float $timeout): string { $buffer = ''; @@ -56,7 +62,10 @@ private function readBytes(int $length): string $write = null; $except = null; - $selected = stream_select($read, $write, $except, $this->timeout); + $timeoutSeconds = (int) $timeout; + $timeoutMicroseconds = (int) (($timeout - $timeoutSeconds) * 1000000); + + $selected = stream_select($read, $write, $except, $timeoutSeconds, $timeoutMicroseconds); if ($selected === false) { throw new RuntimeException('Failed to select stream.'); }