getMessage()), 0, $exception ); } return \pack("CL", 0, \strlen($data)) . $data; } /** * @param callable $push * * @return \Generator * * @throws ChannelException * @throws SerializationException */ private static function parser(callable $push): \Generator { while (true) { $header = yield self::HEADER_LENGTH; $data = \unpack("Cprefix/Llength", $header); if ($data["prefix"] !== 0) { $data = $header . yield; throw new ChannelException("Invalid packet received: " . self::encodeUnprintableChars($data)); } $data = yield $data["length"]; // Attempt to unserialize the received data. try { $result = \unserialize($data); if ($result === false && $data !== \serialize(false)) { throw new ChannelException("Received invalid data: " . self::encodeUnprintableChars($data)); } } catch (\Throwable $exception) { throw new SerializationException("Exception thrown when unserializing data", 0, $exception); } $push($result); } } /** * @param string $data Binary data. * * @return string Unprintable characters encoded as \x##. */ private static function encodeUnprintableChars(string $data): string { return \preg_replace_callback("/[^\x20-\x7e]/", function (array $matches): string { return "\\x" . \dechex(\ord($matches[0])); }, $data); } }