/**
  * Appends AMQP protocol header to buffer.
  *
  * @param Buffer $buffer
  */
 public function appendProtocolHeader(Buffer $buffer)
 {
     $buffer->append('AMQP');
     $buffer->appendUint8(0);
     $buffer->appendUint8(0);
     $buffer->appendUint8(9);
     $buffer->appendUint8(1);
 }
Example #2
0
 /**
  * Reads data from stream into {@link readBuffer}.
  */
 protected function read()
 {
     $s = @fread($this->stream, $this->frameMax);
     if (@feof($this->stream)) {
         throw new ClientException("Broken pipe or closed connection.");
     }
     $this->readBuffer->append($s);
     $this->lastRead = microtime(true);
 }
Example #3
0
 /**
  * Reads data from stream into {@link readBuffer}.
  */
 protected function read()
 {
     $s = @fread($this->stream, $this->frameMax);
     if ($s === false) {
         $info = stream_get_meta_data($this->stream);
         if (isset($info["timed_out"]) && $info["timed_out"]) {
             throw new ClientException("Timeout reached while reading from stream.");
         }
     }
     if (@feof($this->stream)) {
         throw new ClientException("Broken pipe or closed connection.");
     }
     $this->readBuffer->append($s);
     $this->lastRead = microtime(true);
 }
Example #4
0
 public function consume($channel, $queue = '', $consumerTag = '', $noLocal = false, $noAck = false, $exclusive = false, $nowait = false, $arguments = [])
 {
     $buffer = new Buffer();
     $buffer->appendUint16(60);
     $buffer->appendUint16(20);
     $buffer->appendInt16(0);
     $buffer->appendUint8(strlen($queue));
     $buffer->append($queue);
     $buffer->appendUint8(strlen($consumerTag));
     $buffer->append($consumerTag);
     $this->getWriter()->appendBits([$noLocal, $noAck, $exclusive, $nowait], $buffer);
     $this->getWriter()->appendTable($arguments, $buffer);
     $frame = new Protocol\MethodFrame(60, 20);
     $frame->channel = $channel;
     $frame->payloadSize = $buffer->getLength();
     $frame->payload = $buffer;
     $this->getWriter()->appendFrame($frame, $this->getWriteBuffer());
     $this->flushWriteBuffer();
     return $this->awaitConsumeOk($channel);
 }
Example #5
0
 /**
  * Callback after channel-level frame has been received.
  *
  * @param AbstractFrame $frame
  */
 public function onFrameReceived(AbstractFrame $frame)
 {
     if ($this->state === ChannelStateEnum::ERROR) {
         throw new ChannelException("Channel in error state.");
     }
     if ($this->state === ChannelStateEnum::CLOSED) {
         throw new ChannelException("Received frame #{$frame->type} on closed channel #{$this->channelId}.");
     }
     if ($frame instanceof MethodFrame) {
         if ($this->state === ChannelStateEnum::CLOSING && !$frame instanceof MethodChannelCloseOkFrame) {
             // drop frames in closing state
             return;
         } elseif ($this->state !== ChannelStateEnum::READY && !$frame instanceof MethodChannelCloseOkFrame) {
             $currentState = $this->state;
             $this->state = ChannelStateEnum::ERROR;
             if ($currentState === ChannelStateEnum::AWAITING_HEADER) {
                 $msg = "Got method frame, expected header frame.";
             } elseif ($currentState === ChannelStateEnum::AWAITING_BODY) {
                 $msg = "Got method frame, expected body frame.";
             } else {
                 throw new \LogicException("Unhandled channel state.");
             }
             $this->client->disconnect(Constants::STATUS_UNEXPECTED_FRAME, $msg);
             throw new ChannelException("Unexpected frame: " . $msg);
         }
         if ($frame instanceof MethodChannelCloseOkFrame) {
             $this->state = ChannelStateEnum::CLOSED;
             if ($this->closeDeferred !== null) {
                 $this->closeDeferred->resolve($this->channelId);
             }
             // break reference cycle, must be called after resolving promise
             unset($this->client);
             // break consumers' reference cycle
             $this->deliverCallbacks = [];
         } elseif ($frame instanceof MethodBasicReturnFrame) {
             $this->returnFrame = $frame;
             $this->state = ChannelStateEnum::AWAITING_HEADER;
         } elseif ($frame instanceof MethodBasicDeliverFrame) {
             $this->deliverFrame = $frame;
             $this->state = ChannelStateEnum::AWAITING_HEADER;
         } elseif ($frame instanceof MethodBasicAckFrame) {
             foreach ($this->ackCallbacks as $callback) {
                 $callback($frame);
             }
         } elseif ($frame instanceof MethodBasicNackFrame) {
             foreach ($this->ackCallbacks as $callback) {
                 $callback($frame);
             }
         } else {
             throw new ChannelException("Unhandled method frame " . get_class($frame) . ".");
         }
     } elseif ($frame instanceof ContentHeaderFrame) {
         if ($this->state === ChannelStateEnum::CLOSING) {
             // drop frames in closing state
             return;
         } elseif ($this->state !== ChannelStateEnum::AWAITING_HEADER) {
             $currentState = $this->state;
             $this->state = ChannelStateEnum::ERROR;
             if ($currentState === ChannelStateEnum::READY) {
                 $msg = "Got header frame, expected method frame.";
             } elseif ($currentState === ChannelStateEnum::AWAITING_BODY) {
                 $msg = "Got header frame, expected content frame.";
             } else {
                 throw new \LogicException("Unhandled channel state.");
             }
             $this->client->disconnect(Constants::STATUS_UNEXPECTED_FRAME, $msg);
             throw new ChannelException("Unexpected frame: " . $msg);
         }
         $this->headerFrame = $frame;
         $this->bodySizeRemaining = $frame->bodySize;
         $this->state = ChannelStateEnum::AWAITING_BODY;
     } elseif ($frame instanceof ContentBodyFrame) {
         if ($this->state === ChannelStateEnum::CLOSING) {
             // drop frames in closing state
             return;
         } elseif ($this->state !== ChannelStateEnum::AWAITING_BODY) {
             $currentState = $this->state;
             $this->state = ChannelStateEnum::ERROR;
             if ($currentState === ChannelStateEnum::READY) {
                 $msg = "Got body frame, expected method frame.";
             } elseif ($currentState === ChannelStateEnum::AWAITING_HEADER) {
                 $msg = "Got body frame, expected header frame.";
             } else {
                 throw new \LogicException("Unhandled channel state.");
             }
             $this->client->disconnect(Constants::STATUS_UNEXPECTED_FRAME, $msg);
             throw new ChannelException("Unexpected frame: " . $msg);
         }
         $this->bodyBuffer->append($frame->payload);
         $this->bodySizeRemaining -= $frame->payloadSize;
         if ($this->bodySizeRemaining < 0) {
             $this->state = ChannelStateEnum::ERROR;
             $this->client->disconnect(Constants::STATUS_SYNTAX_ERROR, "Body overflow, received " . -$this->bodySizeRemaining . " more bytes.");
         } elseif ($this->bodySizeRemaining === 0) {
             $this->state = ChannelStateEnum::READY;
             $this->onBodyComplete();
         }
     } elseif ($frame instanceof HeartbeatFrame) {
         $this->client->disconnect(Constants::STATUS_UNEXPECTED_FRAME, "Got heartbeat on non-zero channel.");
         throw new ChannelException("Unexpected heartbeat frame.");
     } else {
         throw new ChannelException("Unhandled frame " . get_class($frame) . ".");
     }
 }
Example #6
0
 /**
  * Appends AMQP table/array field value to buffer.
  *
  * @param mixed $value
  * @param Buffer $buffer
  */
 public function appendFieldValue($value, Buffer $buffer)
 {
     if (is_string($value)) {
         $buffer->appendUint8(Constants::FIELD_LONG_STRING);
         $buffer->appendUint32(strlen($value));
         $buffer->append($value);
     } elseif (is_int($value)) {
         $buffer->appendUint8(Constants::FIELD_LONG_INT);
         $buffer->appendInt32($value);
     } elseif (is_bool($value)) {
         $buffer->appendUint8(Constants::FIELD_BOOLEAN);
         $buffer->appendUint8(intval($value));
     } elseif (is_float($value)) {
         $buffer->appendUint8(Constants::FIELD_DOUBLE);
         $buffer->appendDouble($value);
     } elseif (is_array($value)) {
         if (array_keys($value) === range(0, count($value) - 1)) {
             // sequential array
             $buffer->appendUint8(Constants::FIELD_ARRAY);
             $this->appendArray($value, $buffer);
         } else {
             $buffer->appendUint8(Constants::FIELD_TABLE);
             $this->appendTable($value, $buffer);
         }
     } elseif (is_null($value)) {
         $buffer->appendUint8(Constants::FIELD_NULL);
     } elseif ($value instanceof \DateTime) {
         $buffer->appendUint8(Constants::FIELD_TIMESTAMP);
         $this->appendTimestamp($value, $buffer);
     } else {
         throw new ProtocolException("Unhandled value type '" . gettype($value) . "' " . (is_object($value) ? "(class " . get_class($value) . ")" : "") . ".");
     }
 }
Example #7
0
 /**
  * Callback after channel-level frame has been received.
  *
  * @param AbstractFrame $frame
  */
 public function onFrameReceived(AbstractFrame $frame)
 {
     if ($this->state === ChannelStateEnum::ERROR) {
         throw new ChannelException("Channel in error state.");
     }
     if ($frame instanceof MethodFrame) {
         if ($this->state !== ChannelStateEnum::READY) {
             $currentState = $this->state;
             $this->state = ChannelStateEnum::ERROR;
             if ($currentState === ChannelStateEnum::AWAITING_HEADER) {
                 $msg = "Got method frame, expected header frame.";
             } elseif ($currentState === ChannelStateEnum::AWAITING_BODY) {
                 $msg = "Got method frame, expected body frame.";
             } else {
                 throw new \LogicException("Unhandled channel state.");
             }
             $this->client->disconnect(Constants::STATUS_UNEXPECTED_FRAME, $msg);
             throw new ChannelException("Unexpected frame: " . $msg);
         }
         if (false) {
             //            } elseif ($frame instanceof MethodConnectionStartFrame) {
             //            } elseif ($frame instanceof MethodConnectionStartOkFrame) {
             //            } elseif ($frame instanceof MethodConnectionSecureFrame) {
             //            } elseif ($frame instanceof MethodConnectionSecureOkFrame) {
             //            } elseif ($frame instanceof MethodConnectionTuneFrame) {
             //            } elseif ($frame instanceof MethodConnectionTuneOkFrame) {
             //            } elseif ($frame instanceof MethodConnectionOpenFrame) {
             //            } elseif ($frame instanceof MethodConnectionOpenOkFrame) {
             //            } elseif ($frame instanceof MethodConnectionCloseFrame) {
             //            } elseif ($frame instanceof MethodConnectionCloseOkFrame) {
             //            } elseif ($frame instanceof MethodConnectionBlockedFrame) {
             //            } elseif ($frame instanceof MethodConnectionUnblockedFrame) {
             //            } elseif ($frame instanceof MethodChannelOpenFrame) {
             //            } elseif ($frame instanceof MethodChannelOpenOkFrame) {
             //            } elseif ($frame instanceof MethodChannelFlowFrame) {
             //            } elseif ($frame instanceof MethodChannelFlowOkFrame) {
             //            } elseif ($frame instanceof MethodChannelCloseFrame) {
             //            } elseif ($frame instanceof MethodChannelCloseOkFrame) {
             //            } elseif ($frame instanceof MethodAccessRequestFrame) {
             //            } elseif ($frame instanceof MethodAccessRequestOkFrame) {
             //            } elseif ($frame instanceof MethodExchangeDeclareFrame) {
             //            } elseif ($frame instanceof MethodExchangeDeclareOkFrame) {
             //            } elseif ($frame instanceof MethodExchangeDeleteFrame) {
             //            } elseif ($frame instanceof MethodExchangeDeleteOkFrame) {
             //            } elseif ($frame instanceof MethodExchangeBindFrame) {
             //            } elseif ($frame instanceof MethodExchangeBindOkFrame) {
             //            } elseif ($frame instanceof MethodExchangeUnbindFrame) {
             //            } elseif ($frame instanceof MethodExchangeUnbindOkFrame) {
             //            } elseif ($frame instanceof MethodQueueDeclareFrame) {
             //            } elseif ($frame instanceof MethodQueueDeclareOkFrame) {
             //            } elseif ($frame instanceof MethodQueueBindFrame) {
             //            } elseif ($frame instanceof MethodQueueBindOkFrame) {
             //            } elseif ($frame instanceof MethodQueuePurgeFrame) {
             //            } elseif ($frame instanceof MethodQueuePurgeOkFrame) {
             //            } elseif ($frame instanceof MethodQueueDeleteFrame) {
             //            } elseif ($frame instanceof MethodQueueDeleteOkFrame) {
             //            } elseif ($frame instanceof MethodQueueUnbindFrame) {
             //            } elseif ($frame instanceof MethodQueueUnbindOkFrame) {
             //            } elseif ($frame instanceof MethodBasicQosFrame) {
             //            } elseif ($frame instanceof MethodBasicQosOkFrame) {
             //            } elseif ($frame instanceof MethodBasicConsumeFrame) {
             //            } elseif ($frame instanceof MethodBasicConsumeOkFrame) {
             //            } elseif ($frame instanceof MethodBasicCancelFrame) {
             //            } elseif ($frame instanceof MethodBasicCancelOkFrame) {
             //            } elseif ($frame instanceof MethodBasicPublishFrame) {
         } elseif ($frame instanceof MethodBasicReturnFrame) {
             $this->returnFrame = $frame;
             $this->state = ChannelStateEnum::AWAITING_HEADER;
         } elseif ($frame instanceof MethodBasicDeliverFrame) {
             $this->deliverFrame = $frame;
             $this->state = ChannelStateEnum::AWAITING_HEADER;
             //            } elseif ($frame instanceof MethodBasicGetFrame) {
             //            } elseif ($frame instanceof MethodBasicGetOkFrame) {
             //            } elseif ($frame instanceof MethodBasicGetEmptyFrame) {
             //            } elseif ($frame instanceof MethodBasicAckFrame) {
             //            } elseif ($frame instanceof MethodBasicRejectFrame) {
             //            } elseif ($frame instanceof MethodBasicRecoverAsyncFrame) {
             //            } elseif ($frame instanceof MethodBasicRecoverFrame) {
             //            } elseif ($frame instanceof MethodBasicRecoverOkFrame) {
             //            } elseif ($frame instanceof MethodBasicNackFrame) {
             //            } elseif ($frame instanceof MethodTxSelectFrame) {
             //            } elseif ($frame instanceof MethodTxSelectOkFrame) {
             //            } elseif ($frame instanceof MethodTxCommitFrame) {
             //            } elseif ($frame instanceof MethodTxCommitOkFrame) {
             //            } elseif ($frame instanceof MethodTxRollbackFrame) {
             //            } elseif ($frame instanceof MethodTxRollbackOkFrame) {
             //            } elseif ($frame instanceof MethodConfirmSelectFrame) {
             //            } elseif ($frame instanceof MethodConfirmSelectOkFrame) {
         } else {
             throw new ChannelException("Unhandled method frame " . get_class($frame) . ".");
         }
     } elseif ($frame instanceof ContentHeaderFrame) {
         if ($this->state !== ChannelStateEnum::AWAITING_HEADER) {
             $currentState = $this->state;
             $this->state = ChannelStateEnum::ERROR;
             if ($currentState === ChannelStateEnum::READY) {
                 $msg = "Got header frame, expected method frame.";
             } elseif ($currentState === ChannelStateEnum::AWAITING_BODY) {
                 $msg = "Got header frame, expected content frame.";
             } else {
                 throw new \LogicException("Unhandled channel state.");
             }
             $this->client->disconnect(Constants::STATUS_UNEXPECTED_FRAME, $msg);
             throw new ChannelException("Unexpected frame: " . $msg);
         }
         $this->headerFrame = $frame;
         $this->bodySizeRemaining = $frame->bodySize;
         $this->state = ChannelStateEnum::AWAITING_BODY;
     } elseif ($frame instanceof ContentBodyFrame) {
         if ($this->state !== ChannelStateEnum::AWAITING_BODY) {
             $currentState = $this->state;
             $this->state = ChannelStateEnum::ERROR;
             if ($currentState === ChannelStateEnum::READY) {
                 $msg = "Got body frame, expected method frame.";
             } elseif ($currentState === ChannelStateEnum::AWAITING_HEADER) {
                 $msg = "Got body frame, expected header frame.";
             } else {
                 throw new \LogicException("Unhandled channel state.");
             }
             $this->client->disconnect(Constants::STATUS_UNEXPECTED_FRAME, $msg);
             throw new ChannelException("Unexpected frame: " . $msg);
         }
         $this->bodyBuffer->append($frame->payload);
         $this->bodySizeRemaining -= $frame->payloadSize;
         if ($this->bodySizeRemaining < 0) {
             $this->state = ChannelStateEnum::ERROR;
             $this->client->disconnect(Constants::STATUS_SYNTAX_ERROR, "Body overflow, received " . -$this->bodySizeRemaining . " more bytes.");
         } elseif ($this->bodySizeRemaining === 0) {
             $this->state = ChannelStateEnum::READY;
             $this->onBodyComplete();
         }
     } elseif ($frame instanceof HeartbeatFrame) {
         $this->client->disconnect(Constants::STATUS_UNEXPECTED_FRAME, "Got heartbeat on non-zero channel.");
         throw new ChannelException("Unexpected heartbeat frame.");
     } else {
         throw new ChannelException("Unhandled frame " . get_class($frame) . ".");
     }
 }