Пример #1
0
 /**
  * Callback after content body has been completely received.
  */
 protected function onBodyComplete()
 {
     if ($this->returnFrame) {
         $content = $this->bodyBuffer->consume($this->bodyBuffer->getLength());
         $message = new Message(null, null, false, $this->returnFrame->exchange, $this->returnFrame->routingKey, $this->headerFrame->toArray(), $content);
         foreach ($this->returnCallbacks as $callback) {
             $callback($message, $this->returnFrame);
         }
         $this->returnFrame = null;
         $this->headerFrame = null;
     } elseif ($this->deliverFrame) {
         $content = $this->bodyBuffer->consume($this->bodyBuffer->getLength());
         if (isset($this->deliverCallbacks[$this->deliverFrame->consumerTag])) {
             $message = new Message($this->deliverFrame->consumerTag, $this->deliverFrame->deliveryTag, $this->deliverFrame->redelivered, $this->deliverFrame->exchange, $this->deliverFrame->routingKey, $this->headerFrame->toArray(), $content);
             $callback = $this->deliverCallbacks[$this->deliverFrame->consumerTag];
             $callback($message, $this, $this->client);
         }
         $this->deliverFrame = null;
         $this->headerFrame = null;
     } elseif ($this->getOkFrame) {
         $content = $this->bodyBuffer->consume($this->bodyBuffer->getLength());
         // deferred has to be first nullified and then resolved, otherwise results in race condition
         $deferred = $this->getDeferred;
         $this->getDeferred = null;
         $deferred->resolve(new Message(null, $this->getOkFrame->deliveryTag, $this->getOkFrame->redelivered, $this->getOkFrame->exchange, $this->getOkFrame->routingKey, $this->headerFrame->toArray(), $content));
         $this->getOkFrame = null;
         $this->headerFrame = null;
     } else {
         throw new \LogicException("Either return or deliver frame has to be handled here.");
     }
 }
Пример #2
0
 /**
  * Writes data from {@link writeBuffer} to stream.
  */
 protected function write()
 {
     if (($written = @fwrite($this->getStream(), $this->writeBuffer->read($this->writeBuffer->getLength()))) === false) {
         throw new ClientException("Could not write data to socket.");
     }
     if ($written === 0) {
         throw new ClientException("Broken pipe or closed connection.");
     }
     fflush($this->getStream());
     // flush internal PHP buffers
     $this->writeBuffer->discard($written);
     $this->lastWrite = microtime(true);
 }
Пример #3
0
 /**
  * Callback after content body has been completely received.
  */
 protected function onBodyComplete()
 {
     if ($this->returnFrame) {
         // TODO
     } elseif ($this->deliverFrame) {
         $content = $this->bodyBuffer->consume($this->bodyBuffer->getLength());
         if (isset($this->deliverCallbacks[$this->deliverFrame->consumerTag])) {
             $msg = new Message($this->deliverFrame->consumerTag, $this->deliverFrame->deliveryTag, $this->deliverFrame->redelivered, $this->deliverFrame->exchange, $this->deliverFrame->routingKey, $this->headerFrame->toArray(), $content);
             $callback = $this->deliverCallbacks[$this->deliverFrame->consumerTag];
             $callback($msg, $this, $this->client);
         }
         $this->deliverFrame = null;
         $this->headerFrame = null;
     } else {
         throw new \LogicException("Either return or deliver frame has to be handled here.");
     }
 }
Пример #4
0
 public function publish($channel, $body, array $headers, $exchange = '', $routingKey = '', $mandatory = false, $immediate = false)
 {
     $buffer = $this->getWriteBuffer();
     $ck = serialize([$channel, $headers, $exchange, $routingKey, $mandatory, $immediate]);
     $c = isset($this->cache[$ck]) ? $this->cache[$ck] : null;
     $flags = 0;
     $off0 = 0;
     $len0 = 0;
     $off1 = 0;
     $len1 = 0;
     $contentTypeLength = null;
     $contentType = null;
     $contentEncodingLength = null;
     $contentEncoding = null;
     $headersBuffer = null;
     $deliveryMode = null;
     $priority = null;
     $correlationIdLength = null;
     $correlationId = null;
     $replyToLength = null;
     $replyTo = null;
     $expirationLength = null;
     $expiration = null;
     $messageIdLength = null;
     $messageId = null;
     $timestamp = null;
     $typeLength = null;
     $type = null;
     $userIdLength = null;
     $userId = null;
     $appIdLength = null;
     $appId = null;
     $clusterIdLength = null;
     $clusterId = null;
     if ($c) {
         $buffer->append($c[0]);
     } else {
         $off0 = $buffer->getLength();
         $buffer->appendUint8(1);
         $buffer->appendUint16($channel);
         $buffer->appendUint32(9 + strlen($exchange) + strlen($routingKey));
         $buffer->appendUint16(60);
         $buffer->appendUint16(40);
         $buffer->appendInt16(0);
         $buffer->appendUint8(strlen($exchange));
         $buffer->append($exchange);
         $buffer->appendUint8(strlen($routingKey));
         $buffer->append($routingKey);
         $this->getWriter()->appendBits([$mandatory, $immediate], $buffer);
         $buffer->appendUint8(206);
         $s = 14;
         if (isset($headers['content-type'])) {
             $flags |= 32768;
             $contentType = $headers['content-type'];
             $s += 1;
             $s += $contentTypeLength = strlen($contentType);
             unset($headers['content-type']);
         }
         if (isset($headers['content-encoding'])) {
             $flags |= 16384;
             $contentEncoding = $headers['content-encoding'];
             $s += 1;
             $s += $contentEncodingLength = strlen($contentEncoding);
             unset($headers['content-encoding']);
         }
         if (isset($headers['delivery-mode'])) {
             $flags |= 4096;
             $deliveryMode = $headers['delivery-mode'];
             $s += 1;
             unset($headers['delivery-mode']);
         }
         if (isset($headers['priority'])) {
             $flags |= 2048;
             $priority = $headers['priority'];
             $s += 1;
             unset($headers['priority']);
         }
         if (isset($headers['correlation-id'])) {
             $flags |= 1024;
             $correlationId = $headers['correlation-id'];
             $s += 1;
             $s += $correlationIdLength = strlen($correlationId);
             unset($headers['correlation-id']);
         }
         if (isset($headers['reply-to'])) {
             $flags |= 512;
             $replyTo = $headers['reply-to'];
             $s += 1;
             $s += $replyToLength = strlen($replyTo);
             unset($headers['reply-to']);
         }
         if (isset($headers['expiration'])) {
             $flags |= 256;
             $expiration = $headers['expiration'];
             $s += 1;
             $s += $expirationLength = strlen($expiration);
             unset($headers['expiration']);
         }
         if (isset($headers['message-id'])) {
             $flags |= 128;
             $messageId = $headers['message-id'];
             $s += 1;
             $s += $messageIdLength = strlen($messageId);
             unset($headers['message-id']);
         }
         if (isset($headers['timestamp'])) {
             $flags |= 64;
             $timestamp = $headers['timestamp'];
             $s += 8;
             unset($headers['timestamp']);
         }
         if (isset($headers['type'])) {
             $flags |= 32;
             $type = $headers['type'];
             $s += 1;
             $s += $typeLength = strlen($type);
             unset($headers['type']);
         }
         if (isset($headers['user-id'])) {
             $flags |= 16;
             $userId = $headers['user-id'];
             $s += 1;
             $s += $userIdLength = strlen($userId);
             unset($headers['user-id']);
         }
         if (isset($headers['app-id'])) {
             $flags |= 8;
             $appId = $headers['app-id'];
             $s += 1;
             $s += $appIdLength = strlen($appId);
             unset($headers['app-id']);
         }
         if (isset($headers['cluster-id'])) {
             $flags |= 4;
             $clusterId = $headers['cluster-id'];
             $s += 1;
             $s += $clusterIdLength = strlen($clusterId);
             unset($headers['cluster-id']);
         }
         if (!empty($headers)) {
             $flags |= 8192;
             $this->getWriter()->appendTable($headers, $headersBuffer = new Buffer());
             $s += $headersBuffer->getLength();
         }
         $buffer->appendUint8(2);
         $buffer->appendUint16($channel);
         $buffer->appendUint32($s);
         $buffer->appendUint16(60);
         $buffer->appendUint16(0);
         $len0 = $buffer->getLength() - $off0;
     }
     $buffer->appendUint64(strlen($body));
     if ($c) {
         $buffer->append($c[1]);
     } else {
         $off1 = $buffer->getLength();
         $buffer->appendUint16($flags);
         if ($flags & 32768) {
             $buffer->appendUint8($contentTypeLength);
             $buffer->append($contentType);
         }
         if ($flags & 16384) {
             $buffer->appendUint8($contentEncodingLength);
             $buffer->append($contentEncoding);
         }
         if ($flags & 8192) {
             $buffer->append($headersBuffer);
         }
         if ($flags & 4096) {
             $buffer->appendUint8($deliveryMode);
         }
         if ($flags & 2048) {
             $buffer->appendUint8($priority);
         }
         if ($flags & 1024) {
             $buffer->appendUint8($correlationIdLength);
             $buffer->append($correlationId);
         }
         if ($flags & 512) {
             $buffer->appendUint8($replyToLength);
             $buffer->append($replyTo);
         }
         if ($flags & 256) {
             $buffer->appendUint8($expirationLength);
             $buffer->append($expiration);
         }
         if ($flags & 128) {
             $buffer->appendUint8($messageIdLength);
             $buffer->append($messageId);
         }
         if ($flags & 64) {
             $this->getWriter()->appendTimestamp($timestamp, $buffer);
         }
         if ($flags & 32) {
             $buffer->appendUint8($typeLength);
             $buffer->append($type);
         }
         if ($flags & 16) {
             $buffer->appendUint8($userIdLength);
             $buffer->append($userId);
         }
         if ($flags & 8) {
             $buffer->appendUint8($appIdLength);
             $buffer->append($appId);
         }
         if ($flags & 4) {
             $buffer->appendUint8($clusterIdLength);
             $buffer->append($clusterId);
         }
         $buffer->appendUint8(206);
         $len1 = $buffer->getLength() - $off1;
     }
     if (!$c) {
         $this->cache[$ck] = [$buffer->read($len0, $off0), $buffer->read($len1, $off1)];
         if (count($this->cache) > 100) {
             reset($this->cache);
             unset($this->cache[key($this->cache)]);
         }
     }
     for ($payloadMax = $this->getFrameMax() - 8, $i = 0, $l = strlen($body); $i < $l; $i += $payloadMax) {
         $payloadSize = $l - $i;
         if ($payloadSize > $payloadMax) {
             $payloadSize = $payloadMax;
         }
         $buffer->appendUint8(3);
         $buffer->appendUint16($channel);
         $buffer->appendUint32($payloadSize);
         $buffer->append(substr($body, $i, $payloadSize));
         $buffer->appendUint8(206);
     }
     return $this->flushWriteBuffer();
 }
Пример #5
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;
 }