private function readLoop() : Generator { try { while ($this->state === ConnectionState::OPEN) { $frame = (yield $this->transport->read()); $this->heartbeatsSinceFrameReceived = 0; if ($frame instanceof HeartbeatFrame) { continue; } elseif ($frame->frameChannelId > 0) { $channelManager = $this->channels[$frame->frameChannelId] ?? null; if ($channelManager === null) { throw ProtocolException::unexpectedFrame($frame, \sprintf('channel #%s is closed', $frame->frameChannelId)); } (yield $channelManager->dispatch($frame)); } elseif ($frame instanceof ConnectionCloseFrame) { (yield $this->transport->close()); throw AmqpException::create($frame->replyText, $frame->replyCode); } else { throw ProtocolException::unexpectedFrame($frame, 'received on channel #0'); } } while ($this->state === ConnectionState::CLOSING) { $frame = (yield $this->transport->read()); if ($frame instanceof ConnectionCloseOkFrame) { (yield $this->transport->close()); (yield $this->onClose()); } } } catch (ChannelClosedException $e) { (yield $this->onClose(SingleConnectionException::closedUnexpectedly($this->options, $e))); } catch (Throwable $e) { assert(Debug::dumpException('read-loop', $e)); (yield $this->onClose($e)); } }
/** * Write a frame to this channel synchronously. * * @param OutgoingFrame $frame The frame to write. * * @throws ChannelClosedException The channel has been closed. */ public function writeSync(OutgoingFrame $frame) { if ($this->stream === null) { throw ChannelClosedException::channelClosed(); } $buffer = $this->serializer->serialize($frame); assert(Debug::dumpOutgoingFrame('#' . (int) $this->stream, $frame)); assert(Debug::dumpOutgoingHex('#' . (int) $this->stream, $buffer)); do { $bytes = @\fwrite($this->stream, $buffer); // @codeCoverageIgnoreStart if ($bytes === false) { $error = \error_get_last(); throw new ErrorException($error['message'], $error['type'], 1, $error['file'], $error['line']); } // @codeCoverageIgnoreEnd $buffer = \substr($buffer, $bytes); } while ($buffer); $this->hasSentFrame = true; }