Пример #1
0
 /**
  * Consumes AMQP frame from buffer.
  *
  * Returns NULL if there are not enough data to construct whole frame.
  *
  * @param Buffer $buffer
  * @return AbstractFrame
  */
 public function consumeFrame(Buffer $buffer)
 {
     // not enough data
     if ($buffer->getLength() < 7) {
         return null;
     }
     $type = $buffer->readUint8(0);
     $channel = $buffer->readUint16(1);
     $payloadSize = $buffer->readUint32(3);
     $payloadOffset = 7;
     // type:uint8=>1 + channel:uint16=>2 + payloadSize:uint32=>4 ==> 7
     // not enough data
     if ($buffer->getLength() < $payloadOffset + $payloadSize + 1) {
         return null;
     }
     $buffer->consume(7);
     $payload = $buffer->consume($payloadSize);
     $frameEnd = $buffer->consumeUint8();
     if ($frameEnd !== Constants::FRAME_END) {
         throw new ProtocolException(sprintf("Frame end byte invalid - expected 0x%02x, got 0x%02x.", Constants::FRAME_END, $frameEnd));
     }
     $frameBuffer = new Buffer($payload);
     if ($type === Constants::FRAME_METHOD) {
         $frame = $this->consumeMethodFrame($frameBuffer);
     } elseif ($type === Constants::FRAME_HEADER) {
         // see https://github.com/pika/pika/blob/master/pika/spec.py class BasicProperties
         $frame = new ContentHeaderFrame();
         $frame->classId = $frameBuffer->consumeUint16();
         $frame->weight = $frameBuffer->consumeUint16();
         $frame->bodySize = $frameBuffer->consumeUint64();
         $frame->flags = $flags = $frameBuffer->consumeUint16();
         if ($flags & ContentHeaderFrame::FLAG_CONTENT_TYPE) {
             $frame->contentType = $frameBuffer->consume($frameBuffer->consumeUint8());
         }
         if ($flags & ContentHeaderFrame::FLAG_CONTENT_ENCODING) {
             $frame->contentEncoding = $frameBuffer->consume($frameBuffer->consumeUint8());
         }
         if ($flags & ContentHeaderFrame::FLAG_HEADERS) {
             $frame->headers = $this->consumeTable($frameBuffer);
         }
         if ($flags & ContentHeaderFrame::FLAG_DELIVERY_MODE) {
             $frame->deliveryMode = $frameBuffer->consumeUint8();
         }
         if ($flags & ContentHeaderFrame::FLAG_PRIORITY) {
             $frame->priority = $frameBuffer->consumeUint8();
         }
         if ($flags & ContentHeaderFrame::FLAG_CORRELATION_ID) {
             $frame->correlationId = $frameBuffer->consume($frameBuffer->consumeUint8());
         }
         if ($flags & ContentHeaderFrame::FLAG_REPLY_TO) {
             $frame->replyTo = $frameBuffer->consume($frameBuffer->consumeUint8());
         }
         if ($flags & ContentHeaderFrame::FLAG_EXPIRATION) {
             $frame->expiration = $frameBuffer->consume($frameBuffer->consumeUint8());
         }
         if ($flags & ContentHeaderFrame::FLAG_MESSAGE_ID) {
             $frame->messageId = $frameBuffer->consume($frameBuffer->consumeUint8());
         }
         if ($flags & ContentHeaderFrame::FLAG_TIMESTAMP) {
             $frame->timestamp = $this->consumeTimestamp($frameBuffer);
         }
         if ($flags & ContentHeaderFrame::FLAG_TYPE) {
             $frame->typeHeader = $frameBuffer->consume($frameBuffer->consumeUint8());
         }
         if ($flags & ContentHeaderFrame::FLAG_USER_ID) {
             $frame->userId = $frameBuffer->consume($frameBuffer->consumeUint8());
         }
         if ($flags & ContentHeaderFrame::FLAG_APP_ID) {
             $frame->appId = $frameBuffer->consume($frameBuffer->consumeUint8());
         }
         if ($flags & ContentHeaderFrame::FLAG_CLUSTER_ID) {
             $frame->clusterId = $frameBuffer->consume($frameBuffer->consumeUint8());
         }
     } elseif ($type === Constants::FRAME_BODY) {
         $frame = new ContentBodyFrame();
         $frame->payload = $frameBuffer->consume($frameBuffer->getLength());
     } elseif ($type === Constants::FRAME_HEARTBEAT) {
         $frame = new HeartbeatFrame();
         if (!$frameBuffer->isEmpty()) {
             throw new ProtocolException("Heartbeat frame must be empty.");
         }
     } else {
         throw new ProtocolException("Unhandled frame type '{$type}'.");
     }
     if (!$frameBuffer->isEmpty()) {
         throw new ProtocolException("Frame buffer not entirely consumed.");
     }
     /** @var AbstractFrame $frame */
     $frame->type = $type;
     $frame->channel = $channel;
     $frame->payloadSize = $payloadSize;
     // DO NOT CALL! ContentBodyFrame uses payload for body
     // $frame->setPayload($payload);
     return $frame;
 }