mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
@@ -92,6 +92,7 @@ LibreNMS contributors:
|
||||
- Marco Di Cerbo <marco@dottoremoe.com> (marcodc)
|
||||
- David Bell <me@geordish.org> (geordish)
|
||||
- Ibrahim Tachijian <barhom@netsat.se> (barhom)
|
||||
- Guillaume Coeugnet <aliasprotect-git@yahoo.fr> (gcoeugnet)
|
||||
|
||||
[1]: http://observium.org/ "Observium web site"
|
||||
Observium was written by:
|
||||
|
||||
@@ -835,6 +835,51 @@ echo '
|
||||
<textarea class="form-control" name="global-config-textarea" id="playsms_to" placeholder="Enter the config options" data-config_id="'.$playsms_url['config_id'].'" data-type="playsms">'.$upd_mobiles.'</textarea>
|
||||
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
$canopsis_host = get_config_by_name('alert.transports.canopsis.host');
|
||||
$canopsis_user = get_config_by_name('alert.transports.canopsis.user');
|
||||
$canopsis_passwd = get_config_by_name('alert.transports.canopsis.passwd');
|
||||
$canopsis_vhost = get_config_by_name('alert.transports.canopsis.vhost');
|
||||
echo '
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion" href="#canopsis_transport_expand"><i class="fa fa-caret-down"></i> Canopsis transport</a> <button name="test-alert" id="test-alert" type="button" data-transport="canopsis" class="btn btn-primary btn-xs pull-right">Test transport</button>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="canopsis_transport_expand" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<div class="form-group has-feedback">
|
||||
<label for="canopsis_host" class="col-sm-4 control-label">Canopsis Hostname </label>
|
||||
<div class="col-sm-4">
|
||||
<input id="canopsis_host" class="form-control" type="text" name="global-config-input" value="'.$canopsis_host['config_value'].'" data-config_id="'.$canopsis_host['config_id'].'">
|
||||
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<label for="canopsis_user" class="col-sm-4 control-label">User</label>
|
||||
<div class="col-sm-4">
|
||||
<input id="canopsis_user" class="form-control" type="text" name="global-config-input" value="'.$canopsis_user['config_value'].'" data-config_id="'.$canopsis_user['config_id'].'">
|
||||
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<label for="canopsis_passwd" class="col-sm-4 control-label">Password</label>
|
||||
<div class="col-sm-4">
|
||||
<input id="canopsis_passwd" class="form-control" type="password" name="global-config-input" value="'.$canopsis_passwd['config_value'].'" data-config_id="'.$canopsis_passwd['config_id'].'">
|
||||
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<label for="canopsis_vhost" class="col-sm-4 control-label">Vhost</label>
|
||||
<div class="col-sm-4">
|
||||
<input id="canopsis_vhost" class="form-control" type="text" name="global-config-input" value="'.$canopsis_vhost['config_value'].'" data-config_id="'.$canopsis_vhost['config_id'].'">
|
||||
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
58
includes/alerts/transport.canopsis.php
Normal file
58
includes/alerts/transport.canopsis.php
Normal file
@@ -0,0 +1,58 @@
|
||||
require_once "./lib/PhpAmqpLib/autoload.php";
|
||||
|
||||
// Configurations
|
||||
$host = $opts["host"];
|
||||
$port = 5672;
|
||||
$user = $opts["user"];
|
||||
$pass = $opts["passwd"];
|
||||
$vhost = $opts["vhost"];
|
||||
$exchange = "canopsis.events";
|
||||
|
||||
// Connection
|
||||
$conn = new PhpAmqpLib\Connection\AMQPConnection($host, $port, $user, $pass, $vhost);
|
||||
$ch = $conn->channel();
|
||||
|
||||
// Declare exchange (if not exist)
|
||||
// exchange_declare($exchange, $type, $passive=false, $durable=false, $auto_delete=true, $internal=false, $nowait=false, $arguments=null, $ticket=null)
|
||||
$ch->exchange_declare($exchange, 'topic', false, true, false);
|
||||
|
||||
// Create Canopsis event, see: https://github.com/capensis/canopsis/wiki/Event-specification
|
||||
switch ($obj['severity'])
|
||||
{
|
||||
case "ok": $state = 0;
|
||||
break;
|
||||
case "warning": $state = 1;
|
||||
break;
|
||||
case "critical": $state = 2;
|
||||
break;
|
||||
default: $state = 3;
|
||||
}
|
||||
$msg_body = array(
|
||||
"timestamp" => time(),
|
||||
"connector" => "librenms",
|
||||
"connector_name" => "LibreNMS1",
|
||||
"event_type" => "check",
|
||||
"source_type" => "resource",
|
||||
"component" => $obj['hostname'],
|
||||
"resource" => $obj['faults'][1]['storage_descr'],
|
||||
"state" => $state,
|
||||
"state_type" => 1,
|
||||
"output" => $obj['msg'],
|
||||
"display_name" => "librenms"
|
||||
);
|
||||
$msg_raw = json_encode($msg_body);
|
||||
|
||||
// Build routing key
|
||||
if ($msg_body['source_type'] == "resource")
|
||||
$msg_rk = $msg_rk . "." . $msg_body['resource'];
|
||||
else
|
||||
$msg_rk = $msg_body['connector'].".".$msg_body['connector_name'].".".$msg_body['event_type'].".".$msg_body['source_type'].".".$msg_body['component'];
|
||||
|
||||
// Publish Event
|
||||
$msg = new PhpAmqpLib\Message\AMQPMessage($msg_raw, array('content_type' => 'application/json', 'delivery_mode' => 2));
|
||||
$ch->basic_publish($msg, $exchange, $msg_rk);
|
||||
|
||||
// Close connection
|
||||
$ch->close();
|
||||
$conn->close();
|
||||
return true;
|
||||
1489
lib/PhpAmqpLib/Channel/AMQPChannel.php
Normal file
1489
lib/PhpAmqpLib/Channel/AMQPChannel.php
Normal file
File diff suppressed because it is too large
Load Diff
419
lib/PhpAmqpLib/Channel/AbstractChannel.php
Normal file
419
lib/PhpAmqpLib/Channel/AbstractChannel.php
Normal file
@@ -0,0 +1,419 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Channel;
|
||||
|
||||
use PhpAmqpLib\Connection\AbstractConnection;
|
||||
use PhpAmqpLib\Exception\AMQPOutOfBoundsException;
|
||||
use PhpAmqpLib\Exception\AMQPOutOfRangeException;
|
||||
use PhpAmqpLib\Exception\AMQPRuntimeException;
|
||||
use PhpAmqpLib\Helper\MiscHelper;
|
||||
use PhpAmqpLib\Helper\Protocol\MethodMap080;
|
||||
use PhpAmqpLib\Helper\Protocol\MethodMap091;
|
||||
use PhpAmqpLib\Helper\Protocol\Protocol080;
|
||||
use PhpAmqpLib\Helper\Protocol\Protocol091;
|
||||
use PhpAmqpLib\Helper\Protocol\Wait080;
|
||||
use PhpAmqpLib\Helper\Protocol\Wait091;
|
||||
use PhpAmqpLib\Message\AMQPMessage;
|
||||
use PhpAmqpLib\Wire\AMQPReader;
|
||||
|
||||
class AbstractChannel
|
||||
{
|
||||
const PROTOCOL_080 = '0.8';
|
||||
const PROTOCOL_091 = '0.9.1';
|
||||
|
||||
public static $PROTOCOL_CONSTANTS_CLASS;
|
||||
|
||||
/** @var array */
|
||||
protected $frame_queue;
|
||||
|
||||
/** @var array */
|
||||
protected $method_queue;
|
||||
|
||||
/** @var bool */
|
||||
protected $auto_decode;
|
||||
|
||||
/** @var string */
|
||||
protected $amqp_protocol_header;
|
||||
|
||||
/** @var bool */
|
||||
protected $debug;
|
||||
|
||||
/** @var \PhpAmqpLib\Connection\AbstractConnection */
|
||||
protected $connection;
|
||||
|
||||
/** @var string */
|
||||
protected $protocolVersion;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $body_size_max = null;
|
||||
|
||||
/** @var \PhpAmqpLib\Helper\Protocol\Protocol080|\PhpAmqpLib\Helper\Protocol\Protocol091 */
|
||||
protected $protocolWriter;
|
||||
|
||||
/** @var \PhpAmqpLib\Helper\Protocol\Wait080|\PhpAmqpLib\Helper\Protocol\Wait091 */
|
||||
protected $waitHelper;
|
||||
|
||||
/** @var \PhpAmqpLib\Helper\Protocol\MethodMap080|\PhpAmqpLib\Helper\Protocol\MethodMap091 */
|
||||
protected $methodMap;
|
||||
|
||||
/** @var string */
|
||||
protected $channel_id;
|
||||
|
||||
/** @var \PhpAmqpLib\Wire\AMQPReader */
|
||||
protected $msg_property_reader;
|
||||
|
||||
/** @var \PhpAmqpLib\Wire\AMQPReader */
|
||||
protected $wait_content_reader;
|
||||
|
||||
/** @var \PhpAmqpLib\Wire\AMQPReader */
|
||||
protected $dispatch_reader;
|
||||
|
||||
/**
|
||||
* @param AbstractConnection $connection
|
||||
* @param $channel_id
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
*/
|
||||
public function __construct(AbstractConnection $connection, $channel_id)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->channel_id = $channel_id;
|
||||
$connection->channels[$channel_id] = $this;
|
||||
$this->frame_queue = array(); // Lower level queue for frames
|
||||
$this->method_queue = array(); // Higher level queue for methods
|
||||
$this->auto_decode = false;
|
||||
$this->debug = defined('AMQP_DEBUG') ? AMQP_DEBUG : false;
|
||||
|
||||
$this->msg_property_reader = new AMQPReader(null);
|
||||
$this->wait_content_reader = new AMQPReader(null);
|
||||
$this->dispatch_reader = new AMQPReader(null);
|
||||
|
||||
$this->protocolVersion = self::getProtocolVersion();
|
||||
switch ($this->protocolVersion) {
|
||||
case self::PROTOCOL_091:
|
||||
self::$PROTOCOL_CONSTANTS_CLASS = 'PhpAmqpLib\Wire\Constants091';
|
||||
$c = self::$PROTOCOL_CONSTANTS_CLASS;
|
||||
$this->amqp_protocol_header = $c::$AMQP_PROTOCOL_HEADER;
|
||||
$this->protocolWriter = new Protocol091();
|
||||
$this->waitHelper = new Wait091();
|
||||
$this->methodMap = new MethodMap091();
|
||||
break;
|
||||
case self::PROTOCOL_080:
|
||||
self::$PROTOCOL_CONSTANTS_CLASS = 'PhpAmqpLib\Wire\Constants080';
|
||||
$c = self::$PROTOCOL_CONSTANTS_CLASS;
|
||||
$this->amqp_protocol_header = $c::$AMQP_PROTOCOL_HEADER;
|
||||
$this->protocolWriter = new Protocol080();
|
||||
$this->waitHelper = new Wait080();
|
||||
$this->methodMap = new MethodMap080();
|
||||
break;
|
||||
default:
|
||||
//this is logic exception (requires code changes to fix), so OutOfRange, not OutOfBounds or Runtime
|
||||
throw new AMQPOutOfRangeException(sprintf('Protocol version %s not implemented.', $this->protocolVersion));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws AMQPOutOfRangeException
|
||||
*/
|
||||
public static function getProtocolVersion()
|
||||
{
|
||||
$protocol = defined('AMQP_PROTOCOL') ? AMQP_PROTOCOL : self::PROTOCOL_091;
|
||||
//adding check here to catch unknown protocol ASAP, as this method may be called from the outside
|
||||
if (!in_array($protocol, array(self::PROTOCOL_080, self::PROTOCOL_091), TRUE)) {
|
||||
throw new AMQPOutOfRangeException(sprintf('Protocol version %s not implemented.', $protocol));
|
||||
}
|
||||
|
||||
return $protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getChannelId()
|
||||
{
|
||||
return $this->channel_id;
|
||||
}
|
||||
|
||||
public function setBodySizeLimit($max_bytes)
|
||||
{
|
||||
$max_bytes = intval($max_bytes);
|
||||
|
||||
if ( $max_bytes > 0 ) {
|
||||
$this->body_size_max = $max_bytes;
|
||||
} else {
|
||||
$this->body_size_max = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AbstractConnection
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMethodQueue()
|
||||
{
|
||||
return $this->method_queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method_sig
|
||||
* @param string $args
|
||||
* @param $content
|
||||
* @return mixed
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
*/
|
||||
public function dispatch($method_sig, $args, $content)
|
||||
{
|
||||
if (!$this->methodMap->valid_method($method_sig)) {
|
||||
throw new AMQPRuntimeException(sprintf(
|
||||
'Unknown AMQP method "%s"',
|
||||
$method_sig
|
||||
));
|
||||
}
|
||||
|
||||
$amqp_method = $this->methodMap->get_method($method_sig);
|
||||
|
||||
if (!method_exists($this, $amqp_method)) {
|
||||
throw new AMQPRuntimeException(sprintf(
|
||||
'Method: "%s" not implemented by class: %s',
|
||||
$amqp_method,
|
||||
get_class($this)
|
||||
));
|
||||
}
|
||||
|
||||
$this->dispatch_reader->reuse($args);
|
||||
|
||||
if ($content == null) {
|
||||
return call_user_func(array($this, $amqp_method), $this->dispatch_reader);
|
||||
}
|
||||
|
||||
return call_user_func(array($this, $amqp_method), $this->dispatch_reader, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $timeout
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function next_frame($timeout = 0)
|
||||
{
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg('waiting for a new frame');
|
||||
}
|
||||
|
||||
if (!empty($this->frame_queue)) {
|
||||
return array_shift($this->frame_queue);
|
||||
}
|
||||
|
||||
return $this->connection->wait_channel($this->channel_id, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $method_sig
|
||||
* @param string $args
|
||||
*/
|
||||
protected function send_method_frame($method_sig, $args = '')
|
||||
{
|
||||
$this->connection->send_channel_method_frame($this->channel_id, $method_sig, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is here for performance reasons to batch calls to fwrite from basic.publish
|
||||
*
|
||||
* @param $method_sig
|
||||
* @param string $args
|
||||
* @param null $pkt
|
||||
* @return null|\PhpAmqpLib\Wire\AMQPWriter
|
||||
*/
|
||||
protected function prepare_method_frame($method_sig, $args = '', $pkt = null)
|
||||
{
|
||||
return $this->connection->prepare_channel_method_frame($this->channel_id, $method_sig, $args, $pkt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AMQPMessage
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
*/
|
||||
public function wait_content()
|
||||
{
|
||||
$frm = $this->next_frame();
|
||||
$frame_type = $frm[0];
|
||||
$payload = $frm[1];
|
||||
|
||||
if ($frame_type != 2) {
|
||||
throw new AMQPRuntimeException('Expecting Content header');
|
||||
}
|
||||
|
||||
$this->wait_content_reader->reuse(mb_substr($payload, 0, 12, 'ASCII'));
|
||||
|
||||
// $payload_reader = new AMQPReader(substr($payload,0,12));
|
||||
$class_id = $this->wait_content_reader->read_short();
|
||||
$weight = $this->wait_content_reader->read_short();
|
||||
|
||||
$body_size = $this->wait_content_reader->read_longlong();
|
||||
|
||||
//hack to avoid creating new instances of AMQPReader;
|
||||
$this->msg_property_reader->reuse(mb_substr($payload, 12, mb_strlen($payload, 'ASCII') - 12, 'ASCII'));
|
||||
|
||||
$msg = new AMQPMessage();
|
||||
$msg->load_properties($this->msg_property_reader);
|
||||
$msg->body_size = $body_size;
|
||||
|
||||
$body_parts = array();
|
||||
$body_received = 0;
|
||||
while (bccomp($body_size, $body_received, 0) == 1) {
|
||||
$frm = $this->next_frame();
|
||||
$frame_type = $frm[0];
|
||||
$payload = $frm[1];
|
||||
|
||||
if ($frame_type != 3) {
|
||||
$PROTOCOL_CONSTANTS_CLASS = self::$PROTOCOL_CONSTANTS_CLASS;
|
||||
throw new AMQPRuntimeException(sprintf(
|
||||
'Expecting Content body, received frame type %s (%s)',
|
||||
$frame_type,
|
||||
$PROTOCOL_CONSTANTS_CLASS::$FRAME_TYPES[$frame_type]
|
||||
));
|
||||
}
|
||||
|
||||
$body_received = bcadd($body_received, mb_strlen($payload, 'ASCII'), 0);
|
||||
|
||||
if ( ! is_null($this->body_size_max) && $body_received > $this->body_size_max ) {
|
||||
$msg->is_truncated = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$body_parts[] = $payload;
|
||||
}
|
||||
|
||||
$msg->body = implode('', $body_parts);
|
||||
|
||||
if ($this->auto_decode && isset($msg->content_encoding)) {
|
||||
try {
|
||||
$msg->body = $msg->body->decode($msg->content_encoding);
|
||||
} catch (\Exception $e) {
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg('Ignoring body decoding exception: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for some expected AMQP methods and dispatch to them.
|
||||
* Unexpected methods are queued up for later calls to this PHP
|
||||
* method.
|
||||
*
|
||||
* @param array $allowed_methods
|
||||
* @param bool $non_blocking
|
||||
* @param int $timeout
|
||||
* @throws \PhpAmqpLib\Exception\AMQPOutOfBoundsException
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
* @return mixed
|
||||
*/
|
||||
public function wait($allowed_methods = null, $non_blocking = false, $timeout = 0)
|
||||
{
|
||||
$PROTOCOL_CONSTANTS_CLASS = self::$PROTOCOL_CONSTANTS_CLASS;
|
||||
|
||||
if ($allowed_methods && $this->debug) {
|
||||
MiscHelper::debug_msg('waiting for ' . implode(', ', $allowed_methods));
|
||||
} elseif ($this->debug) {
|
||||
MiscHelper::debug_msg('waiting for any method');
|
||||
}
|
||||
|
||||
//Process deferred methods
|
||||
foreach ($this->method_queue as $qk => $queued_method) {
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg('checking queue method ' . $qk);
|
||||
}
|
||||
|
||||
$method_sig = $queued_method[0];
|
||||
if ($allowed_methods == null || in_array($method_sig, $allowed_methods)) {
|
||||
unset($this->method_queue[$qk]);
|
||||
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg(sprintf(
|
||||
'Executing queued method: %s: %s',
|
||||
$method_sig,
|
||||
$PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)]
|
||||
));
|
||||
}
|
||||
|
||||
return $this->dispatch($queued_method[0], $queued_method[1], $queued_method[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// No deferred methods? wait for new ones
|
||||
while (true) {
|
||||
$frm = $this->next_frame($timeout);
|
||||
$frame_type = $frm[0];
|
||||
$payload = $frm[1];
|
||||
|
||||
if ($frame_type != 1) {
|
||||
throw new AMQPRuntimeException(sprintf(
|
||||
'Expecting AMQP method, received frame type: %s (%s)',
|
||||
$frame_type,
|
||||
$PROTOCOL_CONSTANTS_CLASS::$FRAME_TYPES[$frame_type]
|
||||
));
|
||||
}
|
||||
|
||||
if (mb_strlen($payload, 'ASCII') < 4) {
|
||||
throw new AMQPOutOfBoundsException('Method frame too short');
|
||||
}
|
||||
|
||||
$method_sig_array = unpack('n2', mb_substr($payload, 0, 4, 'ASCII'));
|
||||
$method_sig = '' . $method_sig_array[1] . ',' . $method_sig_array[2];
|
||||
$args = mb_substr($payload, 4, mb_strlen($payload, 'ASCII') - 4, 'ASCII');
|
||||
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg(sprintf(
|
||||
'> %s: %s',
|
||||
$method_sig,
|
||||
$PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)]
|
||||
));
|
||||
}
|
||||
|
||||
if (in_array($method_sig, $PROTOCOL_CONSTANTS_CLASS::$CONTENT_METHODS)) {
|
||||
$content = $this->wait_content();
|
||||
} else {
|
||||
$content = null;
|
||||
}
|
||||
|
||||
if ($allowed_methods == null ||
|
||||
in_array($method_sig, $allowed_methods) ||
|
||||
in_array($method_sig, $PROTOCOL_CONSTANTS_CLASS::$CLOSE_METHODS)
|
||||
) {
|
||||
return $this->dispatch($method_sig, $args, $content);
|
||||
}
|
||||
|
||||
// Wasn't what we were looking for? save it for later
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg('Queueing for later: $method_sig: '
|
||||
. $PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)]);
|
||||
}
|
||||
$this->method_queue[] = array($method_sig, $args, $content);
|
||||
|
||||
if ($non_blocking) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $handler
|
||||
* @param array $arguments
|
||||
*/
|
||||
protected function dispatch_to_handler($handler, array $arguments)
|
||||
{
|
||||
if (is_callable($handler)) {
|
||||
call_user_func_array($handler, $arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
13
lib/PhpAmqpLib/Connection/AMQPConnection.php
Normal file
13
lib/PhpAmqpLib/Connection/AMQPConnection.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Connection;
|
||||
|
||||
/**
|
||||
* Class AMQPConnection
|
||||
*
|
||||
* Kept for BC
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
class AMQPConnection extends AMQPStreamConnection
|
||||
{
|
||||
}
|
||||
49
lib/PhpAmqpLib/Connection/AMQPLazyConnection.php
Normal file
49
lib/PhpAmqpLib/Connection/AMQPLazyConnection.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Connection;
|
||||
|
||||
class AMQPLazyConnection extends AMQPConnection
|
||||
{
|
||||
/**
|
||||
* Gets socket from current connection
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function getSocket()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return parent::getSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function channel($channel_id = null)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return parent::channel($channel_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|\PhpAmqpLib\Wire\IO\AbstractIO
|
||||
*/
|
||||
protected function getIO()
|
||||
{
|
||||
if (!$this->io) {
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
return $this->io;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the connection be attempted during construction?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function connectOnConstruct()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
56
lib/PhpAmqpLib/Connection/AMQPSSLConnection.php
Normal file
56
lib/PhpAmqpLib/Connection/AMQPSSLConnection.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Connection;
|
||||
|
||||
class AMQPSSLConnection extends AMQPStreamConnection
|
||||
{
|
||||
/**
|
||||
* @param AbstractConnection $host
|
||||
* @param int $port
|
||||
* @param string $user
|
||||
* @param bool $password
|
||||
* @param string $vhost
|
||||
* @param array $ssl_options
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(
|
||||
$host,
|
||||
$port,
|
||||
$user,
|
||||
$password,
|
||||
$vhost = '/',
|
||||
$ssl_options = array(),
|
||||
$options = array()
|
||||
) {
|
||||
$ssl_context = empty($ssl_options) ? null : $this->create_ssl_context($ssl_options);
|
||||
parent::__construct(
|
||||
$host,
|
||||
$port,
|
||||
$user,
|
||||
$password,
|
||||
$vhost,
|
||||
isset($options['insist']) ? $options['insist'] : false,
|
||||
isset($options['login_method']) ? $options['login_method'] : 'AMQPLAIN',
|
||||
isset($options['login_response']) ? $options['login_response'] : null,
|
||||
isset($options['locale']) ? $options['locale'] : 'en_US',
|
||||
isset($options['connection_timeout']) ? $options['connection_timeout'] : 3,
|
||||
isset($options['read_write_timeout']) ? $options['read_write_timeout'] : 3,
|
||||
$ssl_context,
|
||||
isset($options['keepalive']) ? $options['keepalive'] : false,
|
||||
isset($options['heartbeat']) ? $options['heartbeat'] : 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $options
|
||||
* @return resource
|
||||
*/
|
||||
private function create_ssl_context($options)
|
||||
{
|
||||
$ssl_context = stream_context_create();
|
||||
foreach ($options as $k => $v) {
|
||||
stream_context_set_option($ssl_context, 'ssl', $k, $v);
|
||||
}
|
||||
|
||||
return $ssl_context;
|
||||
}
|
||||
}
|
||||
38
lib/PhpAmqpLib/Connection/AMQPSocketConnection.php
Normal file
38
lib/PhpAmqpLib/Connection/AMQPSocketConnection.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Connection;
|
||||
|
||||
use PhpAmqpLib\Wire\IO\SocketIO;
|
||||
|
||||
class AMQPSocketConnection extends AbstractConnection
|
||||
{
|
||||
/**
|
||||
* @param AbstractConnection $host
|
||||
* @param int $port
|
||||
* @param string $user
|
||||
* @param bool $password
|
||||
* @param string $vhost
|
||||
* @param bool $insist
|
||||
* @param string $login_method
|
||||
* @param null $login_response
|
||||
* @param string $locale
|
||||
* @param int $timeout
|
||||
* @param bool $keepalive
|
||||
*/
|
||||
public function __construct(
|
||||
$host,
|
||||
$port,
|
||||
$user,
|
||||
$password,
|
||||
$vhost = '/',
|
||||
$insist = false,
|
||||
$login_method = 'AMQPLAIN',
|
||||
$login_response = null,
|
||||
$locale = 'en_US',
|
||||
$timeout = 3,
|
||||
$keepalive = false
|
||||
) {
|
||||
$io = new SocketIO($host, $port, $timeout, $keepalive);
|
||||
|
||||
parent::__construct($user, $password, $vhost, $insist, $login_method, $login_response, $locale, $io);
|
||||
}
|
||||
}
|
||||
46
lib/PhpAmqpLib/Connection/AMQPStreamConnection.php
Normal file
46
lib/PhpAmqpLib/Connection/AMQPStreamConnection.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Connection;
|
||||
|
||||
use PhpAmqpLib\Wire\IO\StreamIO;
|
||||
|
||||
class AMQPStreamConnection extends AbstractConnection
|
||||
{
|
||||
/**
|
||||
* @param AbstractConnection $host
|
||||
* @param string $port
|
||||
* @param string $user
|
||||
* @param bool $password
|
||||
* @param string $vhost
|
||||
* @param bool $insist
|
||||
* @param string $login_method
|
||||
* @param null $login_response
|
||||
* @param string $locale
|
||||
* @param int $connection_timeout
|
||||
* @param int $read_write_timeout
|
||||
* @param null $context
|
||||
* @param bool $keepalive
|
||||
*/
|
||||
public function __construct(
|
||||
$host,
|
||||
$port,
|
||||
$user,
|
||||
$password,
|
||||
$vhost = '/',
|
||||
$insist = false,
|
||||
$login_method = 'AMQPLAIN',
|
||||
$login_response = null,
|
||||
$locale = 'en_US',
|
||||
$connection_timeout = 3,
|
||||
$read_write_timeout = 3,
|
||||
$context = null,
|
||||
$keepalive = false,
|
||||
$heartbeat = 0
|
||||
) {
|
||||
$io = new StreamIO($host, $port, $connection_timeout, $read_write_timeout, $context, $keepalive, $heartbeat);
|
||||
|
||||
parent::__construct($user, $password, $vhost, $insist, $login_method, $login_response, $locale, $io, $heartbeat);
|
||||
|
||||
// save the params for the use of __clone, this will overwrite the parent
|
||||
$this->construct_params = func_get_args();
|
||||
}
|
||||
}
|
||||
972
lib/PhpAmqpLib/Connection/AbstractConnection.php
Normal file
972
lib/PhpAmqpLib/Connection/AbstractConnection.php
Normal file
@@ -0,0 +1,972 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Connection;
|
||||
|
||||
use PhpAmqpLib\Channel\AbstractChannel;
|
||||
use PhpAmqpLib\Channel\AMQPChannel;
|
||||
use PhpAmqpLib\Exception\AMQPProtocolConnectionException;
|
||||
use PhpAmqpLib\Exception\AMQPRuntimeException;
|
||||
use PhpAmqpLib\Exception\AMQPTimeoutException;
|
||||
use PhpAmqpLib\Helper\MiscHelper;
|
||||
use PhpAmqpLib\Wire\AMQPReader;
|
||||
use PhpAmqpLib\Wire\AMQPWriter;
|
||||
use PhpAmqpLib\Wire\IO\AbstractIO;
|
||||
use PhpAmqpLib\Wire\IO\SocketIO;
|
||||
|
||||
class AbstractConnection extends AbstractChannel
|
||||
{
|
||||
/** @var array */
|
||||
public static $LIBRARY_PROPERTIES = array(
|
||||
'product' => array('S', 'AMQPLib'),
|
||||
'platform' => array('S', 'PHP'),
|
||||
'version' => array('S', '2.4'),
|
||||
'information' => array('S', ''),
|
||||
'copyright' => array('S', ''),
|
||||
'capabilities' => array(
|
||||
'F',
|
||||
array(
|
||||
'authentication_failure_close' => array('t', true),
|
||||
'publisher_confirms' => array('t', true),
|
||||
'consumer_cancel_notify' => array('t', true),
|
||||
'exchange_exchange_bindings' => array('t', true),
|
||||
'basic.nack' => array('t', true),
|
||||
'connection.blocked' => array('t', true)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
/** @var AMQPChannel[] */
|
||||
public $channels = array();
|
||||
|
||||
/** @var int */
|
||||
protected $version_major;
|
||||
|
||||
/** @var int */
|
||||
protected $version_minor;
|
||||
|
||||
/** @var array */
|
||||
protected $server_properties;
|
||||
|
||||
/** @var array */
|
||||
protected $mechanisms;
|
||||
|
||||
/** @var array */
|
||||
protected $locales;
|
||||
|
||||
/** @var bool */
|
||||
protected $wait_tune_ok;
|
||||
|
||||
/** @var string */
|
||||
protected $known_hosts;
|
||||
|
||||
/** @var AMQPReader */
|
||||
protected $input;
|
||||
|
||||
/** @var string */
|
||||
protected $vhost;
|
||||
|
||||
/** @var bool */
|
||||
protected $insist;
|
||||
|
||||
/** @var string */
|
||||
protected $login_method;
|
||||
|
||||
/** @var AMQPWriter */
|
||||
protected $login_response;
|
||||
|
||||
/** @var string */
|
||||
protected $locale;
|
||||
|
||||
/** @var int */
|
||||
protected $heartbeat;
|
||||
|
||||
/** @var SocketIO */
|
||||
protected $sock;
|
||||
|
||||
/** @var int */
|
||||
protected $channel_max = 65535;
|
||||
|
||||
/** @var int */
|
||||
protected $frame_max = 131072;
|
||||
|
||||
/** @var array Constructor parameters for clone */
|
||||
protected $construct_params;
|
||||
|
||||
/** @var bool Close the connection in destructor */
|
||||
protected $close_on_destruct = true;
|
||||
|
||||
/** @var bool Maintain connection status */
|
||||
protected $is_connected = false;
|
||||
|
||||
/** @var \PhpAmqpLib\Wire\IO\AbstractIO */
|
||||
protected $io;
|
||||
|
||||
/** @var \PhpAmqpLib\Wire\AMQPReader */
|
||||
protected $wait_frame_reader;
|
||||
|
||||
/** @var callable Handles connection blocking from the server */
|
||||
private $connection_block_handler;
|
||||
|
||||
/** @var callable Handles connection unblocking from the server */
|
||||
private $connection_unblock_handler;
|
||||
|
||||
/**
|
||||
* Circular buffer to speed up prepare_content().
|
||||
* Max size limited by $prepare_content_cache_max_size.
|
||||
*
|
||||
* @var array
|
||||
* @see prepare_content()
|
||||
*/
|
||||
private $prepare_content_cache;
|
||||
|
||||
/** @var int Maximal size of $prepare_content_cache */
|
||||
private $prepare_content_cache_max_size;
|
||||
|
||||
/**
|
||||
* @param AbstractConnection $user
|
||||
* @param string $password
|
||||
* @param string $vhost
|
||||
* @param bool $insist
|
||||
* @param string $login_method
|
||||
* @param null $login_response
|
||||
* @param string $locale
|
||||
* @param AbstractIO $io
|
||||
* @param int $heartbeat
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct(
|
||||
$user,
|
||||
$password,
|
||||
$vhost = '/',
|
||||
$insist = false,
|
||||
$login_method = 'AMQPLAIN',
|
||||
$login_response = null,
|
||||
$locale = 'en_US',
|
||||
AbstractIO $io,
|
||||
$heartbeat = 0
|
||||
) {
|
||||
// save the params for the use of __clone
|
||||
$this->construct_params = func_get_args();
|
||||
|
||||
$this->wait_frame_reader = new AMQPReader(null);
|
||||
$this->vhost = $vhost;
|
||||
$this->insist = $insist;
|
||||
$this->login_method = $login_method;
|
||||
$this->login_response = $login_response;
|
||||
$this->locale = $locale;
|
||||
$this->io = $io;
|
||||
$this->heartbeat = $heartbeat;
|
||||
|
||||
if ($user && $password) {
|
||||
$this->login_response = new AMQPWriter();
|
||||
$this->login_response->write_table(array(
|
||||
'LOGIN' => array('S', $user),
|
||||
'PASSWORD' => array('S', $password)
|
||||
));
|
||||
|
||||
// Skip the length
|
||||
$responseValue = $this->login_response->getvalue();
|
||||
$this->login_response = mb_substr($responseValue, 4, mb_strlen($responseValue, 'ASCII') - 4, 'ASCII');
|
||||
|
||||
} else {
|
||||
$this->login_response = null;
|
||||
}
|
||||
|
||||
$this->prepare_content_cache = array();
|
||||
$this->prepare_content_cache_max_size = 100;
|
||||
|
||||
// Lazy Connection waits on connecting
|
||||
if ($this->connectOnConstruct()) {
|
||||
$this->connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the AMQP server
|
||||
*/
|
||||
protected function connect()
|
||||
{
|
||||
try {
|
||||
// Loop until we connect
|
||||
while (!$this->isConnected()) {
|
||||
// Assume we will connect, until we dont
|
||||
$this->setIsConnected(true);
|
||||
|
||||
// Connect the socket
|
||||
$this->getIO()->connect();
|
||||
|
||||
$this->channels = array();
|
||||
// The connection object itself is treated as channel 0
|
||||
parent::__construct($this, 0);
|
||||
|
||||
$this->input = new AMQPReader(null, $this->getIO());
|
||||
|
||||
$this->write($this->amqp_protocol_header);
|
||||
$this->wait(array($this->waitHelper->get_wait('connection.start')));
|
||||
$this->x_start_ok(self::$LIBRARY_PROPERTIES, $this->login_method, $this->login_response, $this->locale);
|
||||
|
||||
$this->wait_tune_ok = true;
|
||||
while ($this->wait_tune_ok) {
|
||||
$this->wait(array(
|
||||
$this->waitHelper->get_wait('connection.secure'),
|
||||
$this->waitHelper->get_wait('connection.tune')
|
||||
));
|
||||
}
|
||||
|
||||
$host = $this->x_open($this->vhost, '', $this->insist);
|
||||
if (!$host) {
|
||||
return; // we weren't redirected
|
||||
}
|
||||
|
||||
$this->setIsConnected(false);
|
||||
$this->closeChannels();
|
||||
|
||||
// we were redirected, close the socket, loop and try again
|
||||
$this->close_socket();
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// Something went wrong, set the connection status
|
||||
$this->setIsConnected(false);
|
||||
$this->closeChannels();
|
||||
throw $e; // Rethrow exception
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconnects using the original connection settings.
|
||||
* This will not recreate any channels that were established previously
|
||||
*/
|
||||
public function reconnect()
|
||||
{
|
||||
// Try to close the AMQP connection
|
||||
$this->safeClose();
|
||||
// Reconnect the socket/stream then AMQP
|
||||
$this->getIO()->reconnect();
|
||||
$this->setIsConnected(false); // getIO can initiate the connection setting via LazyConnection, set it here to be sure
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cloning will use the old properties to make a new connection to the same server
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
call_user_func_array(array($this, '__construct'), $this->construct_params);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->close_on_destruct) {
|
||||
$this->safeClose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to close the connection safely
|
||||
*/
|
||||
protected function safeClose()
|
||||
{
|
||||
try {
|
||||
if (isset($this->input) && $this->input) {
|
||||
$this->close();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Nothing here
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $sec
|
||||
* @param int $usec
|
||||
* @return mixed
|
||||
*/
|
||||
public function select($sec, $usec = 0)
|
||||
{
|
||||
return $this->getIO()->select($sec, $usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to not close the connection
|
||||
* it's useful after the fork when you don't want to close parent process connection
|
||||
*
|
||||
* @param bool $close
|
||||
*/
|
||||
public function set_close_on_destruct($close = true)
|
||||
{
|
||||
$this->close_on_destruct = (bool) $close;
|
||||
}
|
||||
|
||||
protected function close_input()
|
||||
{
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg('closing input');
|
||||
}
|
||||
|
||||
if (!is_null($this->input)) {
|
||||
$this->input->close();
|
||||
$this->input = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function close_socket()
|
||||
{
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg('closing socket');
|
||||
}
|
||||
|
||||
if (!is_null($this->getIO())) {
|
||||
$this->getIO()->close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
*/
|
||||
public function write($data)
|
||||
{
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg(sprintf(
|
||||
'< [hex]: %s%s',
|
||||
PHP_EOL,
|
||||
MiscHelper::hexdump($data, $htmloutput = false, $uppercase = true, $return = true)
|
||||
));
|
||||
}
|
||||
|
||||
try {
|
||||
$this->getIO()->write($data);
|
||||
} catch (AMQPRuntimeException $e) {
|
||||
$this->setIsConnected(false);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
protected function do_close()
|
||||
{
|
||||
$this->setIsConnected(false);
|
||||
$this->close_input();
|
||||
$this->close_socket();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
*/
|
||||
public function get_free_channel_id()
|
||||
{
|
||||
for ($i = 1; $i <= $this->channel_max; $i++) {
|
||||
if (!isset($this->channels[$i])) {
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
|
||||
throw new AMQPRuntimeException('No free channel ids');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $channel
|
||||
* @param int $class_id
|
||||
* @param int $weight
|
||||
* @param int $body_size
|
||||
* @param string $packed_properties
|
||||
* @param string $body
|
||||
* @param AMQPWriter $pkt
|
||||
*/
|
||||
public function send_content($channel, $class_id, $weight, $body_size, $packed_properties, $body, $pkt = null)
|
||||
{
|
||||
$this->prepare_content($channel, $class_id, $weight, $body_size, $packed_properties, $body, $pkt);
|
||||
$this->write($pkt->getvalue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new AMQPWriter or mutates the provided $pkt
|
||||
*
|
||||
* @param string $channel
|
||||
* @param int $class_id
|
||||
* @param int $weight
|
||||
* @param int $body_size
|
||||
* @param string $packed_properties
|
||||
* @param string $body
|
||||
* @param AMQPWriter $pkt
|
||||
* @return AMQPWriter
|
||||
*/
|
||||
public function prepare_content($channel, $class_id, $weight, $body_size, $packed_properties, $body, $pkt = null)
|
||||
{
|
||||
if (empty($pkt)) {
|
||||
$pkt = new AMQPWriter();
|
||||
}
|
||||
|
||||
// Content already prepared ?
|
||||
$key_cache = sprintf(
|
||||
'%s|%s|%s|%s',
|
||||
$channel,
|
||||
$packed_properties,
|
||||
$class_id,
|
||||
$weight
|
||||
);
|
||||
if (!isset($this->prepare_content_cache[$key_cache])) {
|
||||
$w = new AMQPWriter();
|
||||
$w->write_octet(2);
|
||||
$w->write_short($channel);
|
||||
$w->write_long(mb_strlen($packed_properties, 'ASCII') + 12);
|
||||
$w->write_short($class_id);
|
||||
$w->write_short($weight);
|
||||
$this->prepare_content_cache[$key_cache] = $w->getvalue();
|
||||
if (count($this->prepare_content_cache) > $this->prepare_content_cache_max_size) {
|
||||
reset($this->prepare_content_cache);
|
||||
$old_key = key($this->prepare_content_cache);
|
||||
unset($this->prepare_content_cache[$old_key]);
|
||||
}
|
||||
}
|
||||
$pkt->write($this->prepare_content_cache[$key_cache]);
|
||||
|
||||
$pkt->write_longlong($body_size);
|
||||
$pkt->write($packed_properties);
|
||||
|
||||
$pkt->write_octet(0xCE);
|
||||
|
||||
|
||||
// memory efficiency: walk the string instead of biting it. good for very large packets (close in size to memory_limit setting)
|
||||
$position = 0;
|
||||
$bodyLength = mb_strlen($body,'ASCII');
|
||||
while ($position <= $bodyLength) {
|
||||
$payload = mb_substr($body, $position, $this->frame_max - 8, 'ASCII');
|
||||
$position += $this->frame_max - 8;
|
||||
|
||||
$pkt->write_octet(3);
|
||||
$pkt->write_short($channel);
|
||||
$pkt->write_long(mb_strlen($payload, 'ASCII'));
|
||||
|
||||
$pkt->write($payload);
|
||||
|
||||
$pkt->write_octet(0xCE);
|
||||
}
|
||||
|
||||
return $pkt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $channel
|
||||
* @param $method_sig
|
||||
* @param string $args
|
||||
* @param null $pkt
|
||||
*/
|
||||
protected function send_channel_method_frame($channel, $method_sig, $args = '', $pkt = null)
|
||||
{
|
||||
$pkt = $this->prepare_channel_method_frame($channel, $method_sig, $args, $pkt);
|
||||
|
||||
$this->write($pkt->getvalue());
|
||||
|
||||
if ($this->debug) {
|
||||
$PROTOCOL_CONSTANTS_CLASS = self::$PROTOCOL_CONSTANTS_CLASS;
|
||||
MiscHelper::debug_msg(sprintf(
|
||||
'< %s: %s',
|
||||
MiscHelper::methodSig($method_sig),
|
||||
$PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new AMQPWriter or mutates the provided $pkt
|
||||
*
|
||||
* @param $channel
|
||||
* @param $method_sig
|
||||
* @param string $args
|
||||
* @param AMQPWriter $pkt
|
||||
* @return null|AMQPWriter
|
||||
*/
|
||||
protected function prepare_channel_method_frame($channel, $method_sig, $args = '', $pkt = null)
|
||||
{
|
||||
if ($args instanceof AMQPWriter) {
|
||||
$args = $args->getvalue();
|
||||
}
|
||||
|
||||
if (empty($pkt)) {
|
||||
$pkt = new AMQPWriter();
|
||||
}
|
||||
|
||||
$pkt->write_octet(1);
|
||||
$pkt->write_short($channel);
|
||||
$pkt->write_long(mb_strlen($args, 'ASCII') + 4); // 4 = length of class_id and method_id
|
||||
// in payload
|
||||
|
||||
$pkt->write_short($method_sig[0]); // class_id
|
||||
$pkt->write_short($method_sig[1]); // method_id
|
||||
$pkt->write($args);
|
||||
|
||||
$pkt->write_octet(0xCE);
|
||||
|
||||
if ($this->debug) {
|
||||
$PROTOCOL_CONSTANTS_CLASS = self::$PROTOCOL_CONSTANTS_CLASS;
|
||||
MiscHelper::debug_msg(sprintf(
|
||||
'< %s: %s',
|
||||
MiscHelper::methodSig($method_sig),
|
||||
$PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)]
|
||||
));
|
||||
}
|
||||
|
||||
return $pkt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a frame from the server
|
||||
*
|
||||
* @param int $timeout
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
* @throws \PhpAmqpLib\Exception\AMQPTimeoutException
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
*/
|
||||
protected function wait_frame($timeout = 0)
|
||||
{
|
||||
$currentTimeout = $this->input->getTimeout();
|
||||
$this->input->setTimeout($timeout);
|
||||
|
||||
try {
|
||||
// frame_type + channel_id + size
|
||||
$this->wait_frame_reader->reuse(
|
||||
$this->input->read(AMQPReader::OCTET + AMQPReader::SHORT + AMQPReader::LONG)
|
||||
);
|
||||
|
||||
$frame_type = $this->wait_frame_reader->read_octet();
|
||||
$channel = $this->wait_frame_reader->read_short();
|
||||
$size = $this->wait_frame_reader->read_long();
|
||||
|
||||
// payload + ch
|
||||
$this->wait_frame_reader->reuse($this->input->read(AMQPReader::OCTET + (int) $size));
|
||||
|
||||
$payload = $this->wait_frame_reader->read($size);
|
||||
$ch = $this->wait_frame_reader->read_octet();
|
||||
|
||||
} catch (AMQPTimeoutException $e) {
|
||||
$this->input->setTimeout($currentTimeout);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->input->setTimeout($currentTimeout);
|
||||
|
||||
if ($ch != 0xCE) {
|
||||
throw new AMQPRuntimeException(sprintf(
|
||||
'Framing error, unexpected byte: %x',
|
||||
$ch
|
||||
));
|
||||
}
|
||||
|
||||
return array($frame_type, $channel, $payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a frame from the server destined for a particular channel.
|
||||
*
|
||||
* @param string $channel_id
|
||||
* @param int $timeout
|
||||
* @return array
|
||||
*/
|
||||
protected function wait_channel($channel_id, $timeout = 0)
|
||||
{
|
||||
while (true) {
|
||||
list($frame_type, $frame_channel, $payload) = $this->wait_frame($timeout);
|
||||
|
||||
if ($frame_channel === 0 && $frame_type === 8) {
|
||||
// skip heartbeat frames
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
if ($frame_channel == $channel_id) {
|
||||
return array($frame_type, $payload);
|
||||
}
|
||||
|
||||
// Not the channel we were looking for. Queue this frame
|
||||
//for later, when the other channel is looking for frames.
|
||||
array_push($this->channels[$frame_channel]->frame_queue, array($frame_type, $payload));
|
||||
|
||||
// If we just queued up a method for channel 0 (the Connection
|
||||
// itself) it's probably a close method in reaction to some
|
||||
// error, so deal with it right away.
|
||||
if (($frame_type == 1) && ($frame_channel == 0)) {
|
||||
$this->wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a channel object identified by the numeric channel_id, or
|
||||
* create that object if it doesn't already exist.
|
||||
*
|
||||
* @param string $channel_id
|
||||
* @return AMQPChannel
|
||||
*/
|
||||
public function channel($channel_id = null)
|
||||
{
|
||||
if (isset($this->channels[$channel_id])) {
|
||||
return $this->channels[$channel_id];
|
||||
} else {
|
||||
$channel_id = $channel_id ? $channel_id : $this->get_free_channel_id();
|
||||
$ch = new AMQPChannel($this->connection, $channel_id);
|
||||
$this->channels[$channel_id] = $ch;
|
||||
|
||||
return $ch;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a connection close
|
||||
*
|
||||
* @param int $reply_code
|
||||
* @param string $reply_text
|
||||
* @param array $method_sig
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function close($reply_code = 0, $reply_text = '', $method_sig = array(0, 0))
|
||||
{
|
||||
if (!$this->protocolWriter || !$this->isConnected()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->closeChannels();
|
||||
|
||||
list($class_id, $method_id, $args) = $this->protocolWriter->connectionClose(
|
||||
$reply_code,
|
||||
$reply_text,
|
||||
$method_sig[0],
|
||||
$method_sig[1]
|
||||
);
|
||||
$this->send_method_frame(array($class_id, $method_id), $args);
|
||||
|
||||
$this->setIsConnected(false);
|
||||
|
||||
return $this->wait(array(
|
||||
$this->waitHelper->get_wait('connection.close_ok')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @return string
|
||||
*/
|
||||
public static function dump_table($table)
|
||||
{
|
||||
$tokens = array();
|
||||
foreach ($table as $name => $value) {
|
||||
switch ($value[0]) {
|
||||
case 'D':
|
||||
$val = $value[1]->n . 'E' . $value[1]->e;
|
||||
break;
|
||||
case 'F':
|
||||
$val = '(' . self::dump_table($value[1]) . ')';
|
||||
break;
|
||||
case 'T':
|
||||
$val = date('Y-m-d H:i:s', $value[1]);
|
||||
break;
|
||||
default:
|
||||
$val = $value[1];
|
||||
}
|
||||
$tokens[] = $name . '=' . $val;
|
||||
}
|
||||
|
||||
return implode(', ', $tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @throws \PhpAmqpLib\Exception\AMQPProtocolConnectionException
|
||||
*/
|
||||
protected function connection_close($args)
|
||||
{
|
||||
$reply_code = $args->read_short();
|
||||
$reply_text = $args->read_shortstr();
|
||||
$class_id = $args->read_short();
|
||||
$method_id = $args->read_short();
|
||||
|
||||
$this->x_close_ok();
|
||||
|
||||
throw new AMQPProtocolConnectionException($reply_code, $reply_text, array($class_id, $method_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms a connection close
|
||||
*/
|
||||
protected function x_close_ok()
|
||||
{
|
||||
$this->send_method_frame(
|
||||
explode(',', $this->waitHelper->get_wait('connection.close_ok'))
|
||||
);
|
||||
$this->do_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm a connection close
|
||||
*/
|
||||
protected function connection_close_ok($args)
|
||||
{
|
||||
$this->do_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $virtual_host
|
||||
* @param string $capabilities
|
||||
* @param bool $insist
|
||||
* @return mixed
|
||||
*/
|
||||
protected function x_open($virtual_host, $capabilities = '', $insist = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_shortstr($virtual_host);
|
||||
$args->write_shortstr($capabilities);
|
||||
$args->write_bits(array($insist));
|
||||
$this->send_method_frame(array(10, 40), $args);
|
||||
|
||||
$wait = array(
|
||||
$this->waitHelper->get_wait('connection.open_ok')
|
||||
);
|
||||
|
||||
if ($this->protocolVersion == '0.8') {
|
||||
$wait[] = $this->waitHelper->get_wait('connection.redirect');
|
||||
}
|
||||
|
||||
return $this->wait($wait);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that the connection is ready
|
||||
*
|
||||
* @param AMQPReader $args
|
||||
*/
|
||||
protected function connection_open_ok($args)
|
||||
{
|
||||
$this->known_hosts = $args->read_shortstr();
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg('Open OK! known_hosts: ' . $this->known_hosts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks the client to use a different server
|
||||
*
|
||||
* @param AMQPReader $args
|
||||
* @return string
|
||||
*/
|
||||
protected function connection_redirect($args)
|
||||
{
|
||||
$host = $args->read_shortstr();
|
||||
$this->known_hosts = $args->read_shortstr();
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg(sprintf(
|
||||
'Redirected to [%s], known_hosts [%s]',
|
||||
$host,
|
||||
$this->known_hosts
|
||||
));
|
||||
}
|
||||
|
||||
return $host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Security mechanism challenge
|
||||
*
|
||||
* @param AMQPReader $args
|
||||
*/
|
||||
protected function connection_secure($args)
|
||||
{
|
||||
$challenge = $args->read_longstr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Security mechanism response
|
||||
*/
|
||||
protected function x_secure_ok($response)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_longstr($response);
|
||||
$this->send_method_frame(array(10, 21), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts connection negotiation
|
||||
*
|
||||
* @param AMQPReader $args
|
||||
*/
|
||||
protected function connection_start($args)
|
||||
{
|
||||
$this->version_major = $args->read_octet();
|
||||
$this->version_minor = $args->read_octet();
|
||||
$this->server_properties = $args->read_table();
|
||||
$this->mechanisms = explode(' ', $args->read_longstr());
|
||||
$this->locales = explode(' ', $args->read_longstr());
|
||||
|
||||
if ($this->debug) {
|
||||
MiscHelper::debug_msg(sprintf(
|
||||
'Start from server, version: %d.%d, properties: %s, mechanisms: %s, locales: %s',
|
||||
$this->version_major,
|
||||
$this->version_minor,
|
||||
self::dump_table($this->server_properties),
|
||||
implode(', ', $this->mechanisms),
|
||||
implode(', ', $this->locales)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $client_properties
|
||||
* @param $mechanism
|
||||
* @param $response
|
||||
* @param $locale
|
||||
*/
|
||||
protected function x_start_ok($client_properties, $mechanism, $response, $locale)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_table($client_properties);
|
||||
$args->write_shortstr($mechanism);
|
||||
$args->write_longstr($response);
|
||||
$args->write_shortstr($locale);
|
||||
$this->send_method_frame(array(10, 11), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proposes connection tuning parameters
|
||||
*
|
||||
* @param AMQPReader $args
|
||||
*/
|
||||
protected function connection_tune($args)
|
||||
{
|
||||
$v = $args->read_short();
|
||||
if ($v) {
|
||||
$this->channel_max = $v;
|
||||
}
|
||||
|
||||
$v = $args->read_long();
|
||||
if ($v) {
|
||||
$this->frame_max = $v;
|
||||
}
|
||||
|
||||
// use server proposed value if not set
|
||||
if ($this->heartbeat === null) {
|
||||
$this->heartbeat = $args->read_short();
|
||||
}
|
||||
|
||||
$this->x_tune_ok($this->channel_max, $this->frame_max, $this->heartbeat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Negotiates connection tuning parameters
|
||||
*
|
||||
* @param $channel_max
|
||||
* @param $frame_max
|
||||
* @param $heartbeat
|
||||
*/
|
||||
protected function x_tune_ok($channel_max, $frame_max, $heartbeat)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($channel_max);
|
||||
$args->write_long($frame_max);
|
||||
$args->write_short($heartbeat);
|
||||
$this->send_method_frame(array(10, 31), $args);
|
||||
$this->wait_tune_ok = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SocketIO
|
||||
*/
|
||||
public function getSocket()
|
||||
{
|
||||
return $this->io->getSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \PhpAmqpLib\Wire\IO\AbstractIO
|
||||
*/
|
||||
protected function getIO()
|
||||
{
|
||||
return $this->io;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles connection blocked notifications
|
||||
*
|
||||
* @param AMQPReader $args
|
||||
*/
|
||||
protected function connection_blocked(AMQPReader $args)
|
||||
{
|
||||
// Call the block handler and pass in the reason
|
||||
$this->dispatch_to_handler($this->connection_block_handler, array($args->read_shortstr()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles connection unblocked notifications
|
||||
*/
|
||||
protected function connection_unblocked(AMQPReader $args)
|
||||
{
|
||||
// No args to an unblock event
|
||||
$this->dispatch_to_handler($this->connection_unblock_handler, array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a handler which is called whenever a connection.block is sent from the server
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function set_connection_block_handler($callback)
|
||||
{
|
||||
$this->connection_block_handler = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a handler which is called whenever a connection.block is sent from the server
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function set_connection_unblock_handler($callback)
|
||||
{
|
||||
$this->connection_unblock_handler = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the connection status
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isConnected()
|
||||
{
|
||||
return $this->is_connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection status
|
||||
*
|
||||
* @param bool $is_connected
|
||||
*/
|
||||
protected function setIsConnected($is_connected)
|
||||
{
|
||||
$this->is_connected = $is_connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes all available channels
|
||||
*/
|
||||
protected function closeChannels()
|
||||
{
|
||||
foreach ($this->channels as $key => $channel) {
|
||||
// channels[0] is this connection object, so don't close it yet
|
||||
if ($key === 0) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$channel->close();
|
||||
} catch (\Exception $e) {
|
||||
/* Ignore closing errors */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the connection be attempted during construction?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function connectOnConstruct()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
16
lib/PhpAmqpLib/Exception/AMQPBasicCancelException.php
Normal file
16
lib/PhpAmqpLib/Exception/AMQPBasicCancelException.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
class AMQPBasicCancelException extends \Exception implements AMQPExceptionInterface
|
||||
{
|
||||
/** @var string */
|
||||
public $consumerTag;
|
||||
|
||||
/**
|
||||
* @param string $consumerTag
|
||||
*/
|
||||
public function __construct($consumerTag)
|
||||
{
|
||||
$this->consumerTag = $consumerTag;
|
||||
}
|
||||
}
|
||||
9
lib/PhpAmqpLib/Exception/AMQPChannelException.php
Normal file
9
lib/PhpAmqpLib/Exception/AMQPChannelException.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
/**
|
||||
* @deprecated use AMQPProtocolChannelException instead
|
||||
*/
|
||||
class AMQPChannelException extends AMQPException
|
||||
{
|
||||
}
|
||||
9
lib/PhpAmqpLib/Exception/AMQPConnectionException.php
Normal file
9
lib/PhpAmqpLib/Exception/AMQPConnectionException.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
/**
|
||||
* @deprecated use AMQPProtocolConnectionException instead
|
||||
*/
|
||||
class AMQPConnectionException extends AMQPException
|
||||
{
|
||||
}
|
||||
46
lib/PhpAmqpLib/Exception/AMQPException.php
Normal file
46
lib/PhpAmqpLib/Exception/AMQPException.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
//TODO refactor usage of static methods
|
||||
use PhpAmqpLib\Channel\AbstractChannel;
|
||||
use PhpAmqpLib\Helper\MiscHelper;
|
||||
|
||||
/**
|
||||
* @deprecated use AMQPProtocolException instead
|
||||
*/
|
||||
class AMQPException extends \Exception
|
||||
{
|
||||
/** @var string */
|
||||
public $amqp_reply_code;
|
||||
|
||||
/** @var int */
|
||||
public $amqp_reply_text;
|
||||
|
||||
/** @var \Exception */
|
||||
public $amqp_method_sig;
|
||||
|
||||
/** @var array */
|
||||
public $args;
|
||||
|
||||
/**
|
||||
* @param string $reply_code
|
||||
* @param int $reply_text
|
||||
* @param \Exception $method_sig
|
||||
*/
|
||||
public function __construct($reply_code, $reply_text, $method_sig)
|
||||
{
|
||||
parent::__construct($reply_text, $reply_code);
|
||||
|
||||
$this->amqp_reply_code = $reply_code; // redundant, but kept for BC
|
||||
$this->amqp_reply_text = $reply_text; // redundant, but kept for BC
|
||||
$this->amqp_method_sig = $method_sig;
|
||||
|
||||
$ms = MiscHelper::methodSig($method_sig);
|
||||
$PROTOCOL_CONSTANTS_CLASS = AbstractChannel::$PROTOCOL_CONSTANTS_CLASS;
|
||||
$mn = isset($PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[$ms])
|
||||
? $PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[$ms]
|
||||
: $mn = '';
|
||||
|
||||
$this->args = array($reply_code, $reply_text, $method_sig, $mn);
|
||||
}
|
||||
}
|
||||
6
lib/PhpAmqpLib/Exception/AMQPExceptionInterface.php
Normal file
6
lib/PhpAmqpLib/Exception/AMQPExceptionInterface.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
interface AMQPExceptionInterface
|
||||
{
|
||||
}
|
||||
6
lib/PhpAmqpLib/Exception/AMQPIOException.php
Normal file
6
lib/PhpAmqpLib/Exception/AMQPIOException.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
class AMQPIOException extends \Exception implements AMQPExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
class AMQPInvalidArgumentException extends \RuntimeException implements AMQPExceptionInterface
|
||||
{
|
||||
}
|
||||
7
lib/PhpAmqpLib/Exception/AMQPLogicException.php
Normal file
7
lib/PhpAmqpLib/Exception/AMQPLogicException.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
class AMQPLogicException extends \LogicException implements AMQPExceptionInterface
|
||||
{
|
||||
|
||||
}
|
||||
6
lib/PhpAmqpLib/Exception/AMQPOutOfBoundsException.php
Normal file
6
lib/PhpAmqpLib/Exception/AMQPOutOfBoundsException.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
class AMQPOutOfBoundsException extends \OutOfBoundsException implements AMQPExceptionInterface
|
||||
{
|
||||
}
|
||||
7
lib/PhpAmqpLib/Exception/AMQPOutOfRangeException.php
Normal file
7
lib/PhpAmqpLib/Exception/AMQPOutOfRangeException.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
class AMQPOutOfRangeException extends \OutOfRangeException implements AMQPExceptionInterface
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
class AMQPProtocolChannelException extends AMQPProtocolException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
class AMQPProtocolConnectionException extends AMQPProtocolException
|
||||
{
|
||||
}
|
||||
44
lib/PhpAmqpLib/Exception/AMQPProtocolException.php
Normal file
44
lib/PhpAmqpLib/Exception/AMQPProtocolException.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
//TODO refactor usage of static methods
|
||||
use PhpAmqpLib\Channel\AbstractChannel;
|
||||
use PhpAmqpLib\Helper\MiscHelper;
|
||||
|
||||
class AMQPProtocolException extends \Exception implements AMQPExceptionInterface
|
||||
{
|
||||
/** @var string */
|
||||
public $amqp_reply_code;
|
||||
|
||||
/** @var int */
|
||||
public $amqp_reply_text;
|
||||
|
||||
/** @var \Exception */
|
||||
public $amqp_method_sig;
|
||||
|
||||
/** @var array */
|
||||
public $args;
|
||||
|
||||
/**
|
||||
* @param string $reply_code
|
||||
* @param int $reply_text
|
||||
* @param \Exception $method_sig
|
||||
*/
|
||||
public function __construct($reply_code, $reply_text, $method_sig)
|
||||
{
|
||||
parent::__construct($reply_text, $reply_code);
|
||||
|
||||
$this->amqp_reply_code = $reply_code; // redundant, but kept for BC
|
||||
$this->amqp_reply_text = $reply_text; // redundant, but kept for BC
|
||||
$this->amqp_method_sig = $method_sig;
|
||||
|
||||
$ms = MiscHelper::methodSig($method_sig);
|
||||
|
||||
$PROTOCOL_CONSTANTS_CLASS = AbstractChannel::$PROTOCOL_CONSTANTS_CLASS;
|
||||
$mn = isset($PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[$ms])
|
||||
? $PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[$ms]
|
||||
: $mn = '';
|
||||
|
||||
$this->args = array($reply_code, $reply_text, $method_sig, $mn);
|
||||
}
|
||||
}
|
||||
6
lib/PhpAmqpLib/Exception/AMQPRuntimeException.php
Normal file
6
lib/PhpAmqpLib/Exception/AMQPRuntimeException.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
class AMQPRuntimeException extends \RuntimeException implements AMQPExceptionInterface
|
||||
{
|
||||
}
|
||||
6
lib/PhpAmqpLib/Exception/AMQPTimeoutException.php
Normal file
6
lib/PhpAmqpLib/Exception/AMQPTimeoutException.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Exception;
|
||||
|
||||
class AMQPTimeoutException extends \RuntimeException implements AMQPExceptionInterface
|
||||
{
|
||||
}
|
||||
126
lib/PhpAmqpLib/Helper/MiscHelper.php
Normal file
126
lib/PhpAmqpLib/Helper/MiscHelper.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Helper;
|
||||
|
||||
class MiscHelper
|
||||
{
|
||||
public static function debug_msg($s)
|
||||
{
|
||||
echo $s . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $a
|
||||
* @return string
|
||||
*/
|
||||
public static function methodSig($a)
|
||||
{
|
||||
if (is_string($a)) {
|
||||
return $a;
|
||||
} else {
|
||||
return sprintf('%d,%d', $a[0], $a[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $bytes
|
||||
*/
|
||||
public static function saveBytes($bytes)
|
||||
{
|
||||
$fh = fopen('/tmp/bytes', 'wb');
|
||||
fwrite($fh, $bytes);
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a number (either int or float) and returns an array containing its integer part as first element and its
|
||||
* decimal part mutliplied by 10^6. Useful for some PHP stream functions that need seconds and microseconds as
|
||||
* different arguments
|
||||
*
|
||||
* @param $number
|
||||
* @return array
|
||||
*/
|
||||
public static function splitSecondsMicroseconds($number)
|
||||
{
|
||||
return array(floor($number), ($number - floor($number)) * 1000000);
|
||||
}
|
||||
|
||||
/**
|
||||
* View any string as a hexdump.
|
||||
*
|
||||
* This is most commonly used to view binary data from streams
|
||||
* or sockets while debugging, but can be used to view any string
|
||||
* with non-viewable characters.
|
||||
*
|
||||
* @version 1.3.2
|
||||
* @author Aidan Lister <aidan@php.net>
|
||||
* @author Peter Waller <iridum@php.net>
|
||||
* @link http://aidanlister.com/repos/v/function.hexdump.php
|
||||
*
|
||||
* @param string $data The string to be dumped
|
||||
* @param bool $htmloutput Set to false for non-HTML output
|
||||
* @param bool $uppercase Set to true for uppercase hex
|
||||
* @param bool $return Set to true to return the dump
|
||||
* @return string
|
||||
*/
|
||||
public static function hexdump($data, $htmloutput = true, $uppercase = false, $return = false)
|
||||
{
|
||||
// Init
|
||||
$hexi = '';
|
||||
$ascii = '';
|
||||
$dump = $htmloutput ? '<pre>' : '';
|
||||
$offset = 0;
|
||||
$len = mb_strlen($data, 'ASCII');
|
||||
|
||||
// Upper or lower case hexidecimal
|
||||
$hexFormat = $uppercase ? 'X' : 'x';
|
||||
|
||||
// Iterate string
|
||||
for ($i = $j = 0; $i < $len; $i++) {
|
||||
// Convert to hexidecimal
|
||||
// We must use concatenation here because the $hexFormat value
|
||||
// is needed for sprintf() to parse the format
|
||||
$hexi .= sprintf('%02' . $hexFormat . ' ', ord($data[$i]));
|
||||
|
||||
// Replace non-viewable bytes with '.'
|
||||
if (ord($data[$i]) >= 32) {
|
||||
$ascii .= $htmloutput ? htmlentities($data[$i]) : $data[$i];
|
||||
} else {
|
||||
$ascii .= '.';
|
||||
}
|
||||
|
||||
// Add extra column spacing
|
||||
if ($j === 7) {
|
||||
$hexi .= ' ';
|
||||
$ascii .= ' ';
|
||||
}
|
||||
|
||||
// Add row
|
||||
if (++$j === 16 || $i === $len - 1) {
|
||||
// Join the hexi / ascii output
|
||||
// We must use concatenation here because the $hexFormat value
|
||||
// is needed for sprintf() to parse the format
|
||||
$dump .= sprintf('%04' . $hexFormat . ' %-49s %s', $offset, $hexi, $ascii);
|
||||
|
||||
// Reset vars
|
||||
$hexi = $ascii = '';
|
||||
$offset += 16;
|
||||
$j = 0;
|
||||
|
||||
// Add newline
|
||||
if ($i !== $len - 1) {
|
||||
$dump .= PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finish dump
|
||||
$dump .= $htmloutput ? '</pre>' : '';
|
||||
$dump .= PHP_EOL;
|
||||
|
||||
if ($return) {
|
||||
return $dump;
|
||||
}
|
||||
|
||||
echo $dump;
|
||||
}
|
||||
}
|
||||
120
lib/PhpAmqpLib/Helper/Protocol/MethodMap080.php
Normal file
120
lib/PhpAmqpLib/Helper/Protocol/MethodMap080.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
/* This file was autogenerated by spec/parser.php - Do not modify */
|
||||
|
||||
namespace PhpAmqpLib\Helper\Protocol;
|
||||
|
||||
class MethodMap080
|
||||
{
|
||||
|
||||
protected $method_map = array(
|
||||
'10,10' => 'connection_start',
|
||||
'10,11' => 'connection_start_ok',
|
||||
'10,20' => 'connection_secure',
|
||||
'10,21' => 'connection_secure_ok',
|
||||
'10,30' => 'connection_tune',
|
||||
'10,31' => 'connection_tune_ok',
|
||||
'10,40' => 'connection_open',
|
||||
'10,41' => 'connection_open_ok',
|
||||
'10,50' => 'connection_redirect',
|
||||
'10,60' => 'connection_close',
|
||||
'10,61' => 'connection_close_ok',
|
||||
'20,10' => 'channel_open',
|
||||
'20,11' => 'channel_open_ok',
|
||||
'20,20' => 'channel_flow',
|
||||
'20,21' => 'channel_flow_ok',
|
||||
'20,30' => 'channel_alert',
|
||||
'20,40' => 'channel_close',
|
||||
'20,41' => 'channel_close_ok',
|
||||
'30,10' => 'access_request',
|
||||
'30,11' => 'access_request_ok',
|
||||
'40,10' => 'exchange_declare',
|
||||
'40,11' => 'exchange_declare_ok',
|
||||
'40,20' => 'exchange_delete',
|
||||
'40,21' => 'exchange_delete_ok',
|
||||
'50,10' => 'queue_declare',
|
||||
'50,11' => 'queue_declare_ok',
|
||||
'50,20' => 'queue_bind',
|
||||
'50,21' => 'queue_bind_ok',
|
||||
'50,30' => 'queue_purge',
|
||||
'50,31' => 'queue_purge_ok',
|
||||
'50,40' => 'queue_delete',
|
||||
'50,41' => 'queue_delete_ok',
|
||||
'50,50' => 'queue_unbind',
|
||||
'50,51' => 'queue_unbind_ok',
|
||||
'60,10' => 'basic_qos',
|
||||
'60,11' => 'basic_qos_ok',
|
||||
'60,20' => 'basic_consume',
|
||||
'60,21' => 'basic_consume_ok',
|
||||
'60,30' => 'basic_cancel',
|
||||
'60,31' => 'basic_cancel_ok',
|
||||
'60,40' => 'basic_publish',
|
||||
'60,50' => 'basic_return',
|
||||
'60,60' => 'basic_deliver',
|
||||
'60,70' => 'basic_get',
|
||||
'60,71' => 'basic_get_ok',
|
||||
'60,72' => 'basic_get_empty',
|
||||
'60,80' => 'basic_ack',
|
||||
'60,90' => 'basic_reject',
|
||||
'60,100' => 'basic_recover_async',
|
||||
'60,110' => 'basic_recover',
|
||||
'60,111' => 'basic_recover_ok',
|
||||
'70,10' => 'file_qos',
|
||||
'70,11' => 'file_qos_ok',
|
||||
'70,20' => 'file_consume',
|
||||
'70,21' => 'file_consume_ok',
|
||||
'70,30' => 'file_cancel',
|
||||
'70,31' => 'file_cancel_ok',
|
||||
'70,40' => 'file_open',
|
||||
'70,41' => 'file_open_ok',
|
||||
'70,50' => 'file_stage',
|
||||
'70,60' => 'file_publish',
|
||||
'70,70' => 'file_return',
|
||||
'70,80' => 'file_deliver',
|
||||
'70,90' => 'file_ack',
|
||||
'70,100' => 'file_reject',
|
||||
'80,10' => 'stream_qos',
|
||||
'80,11' => 'stream_qos_ok',
|
||||
'80,20' => 'stream_consume',
|
||||
'80,21' => 'stream_consume_ok',
|
||||
'80,30' => 'stream_cancel',
|
||||
'80,31' => 'stream_cancel_ok',
|
||||
'80,40' => 'stream_publish',
|
||||
'80,50' => 'stream_return',
|
||||
'80,60' => 'stream_deliver',
|
||||
'90,10' => 'tx_select',
|
||||
'90,11' => 'tx_select_ok',
|
||||
'90,20' => 'tx_commit',
|
||||
'90,21' => 'tx_commit_ok',
|
||||
'90,30' => 'tx_rollback',
|
||||
'90,31' => 'tx_rollback_ok',
|
||||
'100,10' => 'dtx_select',
|
||||
'100,11' => 'dtx_select_ok',
|
||||
'100,20' => 'dtx_start',
|
||||
'100,21' => 'dtx_start_ok',
|
||||
'110,10' => 'tunnel_request',
|
||||
'120,10' => 'test_integer',
|
||||
'120,11' => 'test_integer_ok',
|
||||
'120,20' => 'test_string',
|
||||
'120,21' => 'test_string_ok',
|
||||
'120,30' => 'test_table',
|
||||
'120,31' => 'test_table_ok',
|
||||
'120,40' => 'test_content',
|
||||
'120,41' => 'test_content_ok',
|
||||
);
|
||||
|
||||
|
||||
|
||||
public function get_method($method_sig)
|
||||
{
|
||||
return $this->method_map[$method_sig];
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function valid_method($method_sig)
|
||||
{
|
||||
return array_key_exists($method_sig, $this->method_map);
|
||||
}
|
||||
|
||||
}
|
||||
91
lib/PhpAmqpLib/Helper/Protocol/MethodMap091.php
Normal file
91
lib/PhpAmqpLib/Helper/Protocol/MethodMap091.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/* This file was autogenerated by spec/parser.php - Do not modify */
|
||||
|
||||
namespace PhpAmqpLib\Helper\Protocol;
|
||||
|
||||
class MethodMap091
|
||||
{
|
||||
|
||||
protected $method_map = array(
|
||||
'10,10' => 'connection_start',
|
||||
'10,11' => 'connection_start_ok',
|
||||
'10,20' => 'connection_secure',
|
||||
'10,21' => 'connection_secure_ok',
|
||||
'10,30' => 'connection_tune',
|
||||
'10,31' => 'connection_tune_ok',
|
||||
'10,40' => 'connection_open',
|
||||
'10,41' => 'connection_open_ok',
|
||||
'10,50' => 'connection_close',
|
||||
'10,51' => 'connection_close_ok',
|
||||
'10,60' => 'connection_blocked',
|
||||
'10,61' => 'connection_unblocked',
|
||||
'20,10' => 'channel_open',
|
||||
'20,11' => 'channel_open_ok',
|
||||
'20,20' => 'channel_flow',
|
||||
'20,21' => 'channel_flow_ok',
|
||||
'20,40' => 'channel_close',
|
||||
'20,41' => 'channel_close_ok',
|
||||
'30,10' => 'access_request',
|
||||
'30,11' => 'access_request_ok',
|
||||
'40,10' => 'exchange_declare',
|
||||
'40,11' => 'exchange_declare_ok',
|
||||
'40,20' => 'exchange_delete',
|
||||
'40,21' => 'exchange_delete_ok',
|
||||
'40,30' => 'exchange_bind',
|
||||
'40,31' => 'exchange_bind_ok',
|
||||
'40,40' => 'exchange_unbind',
|
||||
'40,51' => 'exchange_unbind_ok',
|
||||
'50,10' => 'queue_declare',
|
||||
'50,11' => 'queue_declare_ok',
|
||||
'50,20' => 'queue_bind',
|
||||
'50,21' => 'queue_bind_ok',
|
||||
'50,30' => 'queue_purge',
|
||||
'50,31' => 'queue_purge_ok',
|
||||
'50,40' => 'queue_delete',
|
||||
'50,41' => 'queue_delete_ok',
|
||||
'50,50' => 'queue_unbind',
|
||||
'50,51' => 'queue_unbind_ok',
|
||||
'60,10' => 'basic_qos',
|
||||
'60,11' => 'basic_qos_ok',
|
||||
'60,20' => 'basic_consume',
|
||||
'60,21' => 'basic_consume_ok',
|
||||
'60,30' => 'basic_cancel_from_server',
|
||||
'60,31' => 'basic_cancel_ok',
|
||||
'60,40' => 'basic_publish',
|
||||
'60,50' => 'basic_return',
|
||||
'60,60' => 'basic_deliver',
|
||||
'60,70' => 'basic_get',
|
||||
'60,71' => 'basic_get_ok',
|
||||
'60,72' => 'basic_get_empty',
|
||||
'60,80' => 'basic_ack_from_server',
|
||||
'60,90' => 'basic_reject',
|
||||
'60,100' => 'basic_recover_async',
|
||||
'60,110' => 'basic_recover',
|
||||
'60,111' => 'basic_recover_ok',
|
||||
'60,120' => 'basic_nack_from_server',
|
||||
'90,10' => 'tx_select',
|
||||
'90,11' => 'tx_select_ok',
|
||||
'90,20' => 'tx_commit',
|
||||
'90,21' => 'tx_commit_ok',
|
||||
'90,30' => 'tx_rollback',
|
||||
'90,31' => 'tx_rollback_ok',
|
||||
'85,10' => 'confirm_select',
|
||||
'85,11' => 'confirm_select_ok',
|
||||
);
|
||||
|
||||
|
||||
|
||||
public function get_method($method_sig)
|
||||
{
|
||||
return $this->method_map[$method_sig];
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function valid_method($method_sig)
|
||||
{
|
||||
return array_key_exists($method_sig, $this->method_map);
|
||||
}
|
||||
|
||||
}
|
||||
1260
lib/PhpAmqpLib/Helper/Protocol/Protocol080.php
Normal file
1260
lib/PhpAmqpLib/Helper/Protocol/Protocol080.php
Normal file
File diff suppressed because it is too large
Load Diff
870
lib/PhpAmqpLib/Helper/Protocol/Protocol091.php
Normal file
870
lib/PhpAmqpLib/Helper/Protocol/Protocol091.php
Normal file
@@ -0,0 +1,870 @@
|
||||
<?php
|
||||
|
||||
/* This file was autogenerated by spec/parser.php - Do not modify */
|
||||
|
||||
namespace PhpAmqpLib\Helper\Protocol;
|
||||
|
||||
use PhpAmqpLib\Wire\AMQPWriter;
|
||||
use PhpAmqpLib\Wire\AMQPReader;
|
||||
|
||||
class Protocol091
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function connectionStart($version_major = 0, $version_minor = 9, $server_properties, $mechanisms = 'PLAIN', $locales = 'en_US')
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_octet($version_major);
|
||||
$args->write_octet($version_minor);
|
||||
$args->write_table(empty($server_properties) ? array() : $server_properties);
|
||||
$args->write_longstr($mechanisms);
|
||||
$args->write_longstr($locales);
|
||||
return array(10, 10, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function connectionStartOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_table();
|
||||
$ret[] = $args->read_shortstr();
|
||||
$ret[] = $args->read_longstr();
|
||||
$ret[] = $args->read_shortstr();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function connectionSecure($challenge)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_longstr($challenge);
|
||||
return array(10, 20, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function connectionSecureOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_longstr();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function connectionTune($channel_max = 0, $frame_max = 0, $heartbeat = 0)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($channel_max);
|
||||
$args->write_long($frame_max);
|
||||
$args->write_short($heartbeat);
|
||||
return array(10, 30, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function connectionTuneOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_short();
|
||||
$ret[] = $args->read_long();
|
||||
$ret[] = $args->read_short();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function connectionOpen($virtual_host = '/', $capabilities = '', $insist = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_shortstr($virtual_host);
|
||||
$args->write_shortstr($capabilities);
|
||||
$args->write_bits(array($insist));
|
||||
return array(10, 40, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function connectionOpenOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_shortstr();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function connectionClose($reply_code, $reply_text = '', $class_id, $method_id)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($reply_code);
|
||||
$args->write_shortstr($reply_text);
|
||||
$args->write_short($class_id);
|
||||
$args->write_short($method_id);
|
||||
return array(10, 50, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function connectionCloseOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function connectionBlocked($reason = '')
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_shortstr($reason);
|
||||
return array(10, 60, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function connectionUnblocked($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function channelOpen($out_of_band = '')
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_shortstr($out_of_band);
|
||||
return array(20, 10, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function channelOpenOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_longstr();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function channelFlow($active)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_bits(array($active));
|
||||
return array(20, 20, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function channelFlowOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_bit();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function channelClose($reply_code, $reply_text = '', $class_id, $method_id)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($reply_code);
|
||||
$args->write_shortstr($reply_text);
|
||||
$args->write_short($class_id);
|
||||
$args->write_short($method_id);
|
||||
return array(20, 40, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function channelCloseOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function accessRequest($realm = '/data', $exclusive = false, $passive = true, $active = true, $write = true, $read = true)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_shortstr($realm);
|
||||
$args->write_bits(array($exclusive, $passive, $active, $write, $read));
|
||||
return array(30, 10, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function accessRequestOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_short();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function exchangeDeclare($ticket = 0, $exchange, $type = 'direct', $passive = false, $durable = false, $auto_delete = false, $internal = false, $nowait = false, $arguments = array())
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($exchange);
|
||||
$args->write_shortstr($type);
|
||||
$args->write_bits(array($passive, $durable, $auto_delete, $internal, $nowait));
|
||||
$args->write_table(empty($arguments) ? array() : $arguments);
|
||||
return array(40, 10, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function exchangeDeclareOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function exchangeDelete($ticket = 0, $exchange, $if_unused = false, $nowait = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($exchange);
|
||||
$args->write_bits(array($if_unused, $nowait));
|
||||
return array(40, 20, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function exchangeDeleteOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function exchangeBind($ticket = 0, $destination, $source, $routing_key = '', $nowait = false, $arguments = array())
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($destination);
|
||||
$args->write_shortstr($source);
|
||||
$args->write_shortstr($routing_key);
|
||||
$args->write_bits(array($nowait));
|
||||
$args->write_table(empty($arguments) ? array() : $arguments);
|
||||
return array(40, 30, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function exchangeBindOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function exchangeUnbind($ticket = 0, $destination, $source, $routing_key = '', $nowait = false, $arguments = array())
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($destination);
|
||||
$args->write_shortstr($source);
|
||||
$args->write_shortstr($routing_key);
|
||||
$args->write_bits(array($nowait));
|
||||
$args->write_table(empty($arguments) ? array() : $arguments);
|
||||
return array(40, 40, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function exchangeUnbindOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function queueDeclare($ticket = 0, $queue = '', $passive = false, $durable = false, $exclusive = false, $auto_delete = false, $nowait = false, $arguments = array())
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($queue);
|
||||
$args->write_bits(array($passive, $durable, $exclusive, $auto_delete, $nowait));
|
||||
$args->write_table(empty($arguments) ? array() : $arguments);
|
||||
return array(50, 10, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function queueDeclareOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_shortstr();
|
||||
$ret[] = $args->read_long();
|
||||
$ret[] = $args->read_long();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function queueBind($ticket = 0, $queue = '', $exchange, $routing_key = '', $nowait = false, $arguments = array())
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($queue);
|
||||
$args->write_shortstr($exchange);
|
||||
$args->write_shortstr($routing_key);
|
||||
$args->write_bits(array($nowait));
|
||||
$args->write_table(empty($arguments) ? array() : $arguments);
|
||||
return array(50, 20, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function queueBindOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function queuePurge($ticket = 0, $queue = '', $nowait = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($queue);
|
||||
$args->write_bits(array($nowait));
|
||||
return array(50, 30, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function queuePurgeOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_long();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function queueDelete($ticket = 0, $queue = '', $if_unused = false, $if_empty = false, $nowait = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($queue);
|
||||
$args->write_bits(array($if_unused, $if_empty, $nowait));
|
||||
return array(50, 40, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function queueDeleteOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_long();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function queueUnbind($ticket = 0, $queue = '', $exchange, $routing_key = '', $arguments = array())
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($queue);
|
||||
$args->write_shortstr($exchange);
|
||||
$args->write_shortstr($routing_key);
|
||||
$args->write_table(empty($arguments) ? array() : $arguments);
|
||||
return array(50, 50, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function queueUnbindOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicQos($prefetch_size = 0, $prefetch_count = 0, $global = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_long($prefetch_size);
|
||||
$args->write_short($prefetch_count);
|
||||
$args->write_bits(array($global));
|
||||
return array(60, 10, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function basicQosOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicConsume($ticket = 0, $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false, $arguments = array())
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($queue);
|
||||
$args->write_shortstr($consumer_tag);
|
||||
$args->write_bits(array($no_local, $no_ack, $exclusive, $nowait));
|
||||
$args->write_table(empty($arguments) ? array() : $arguments);
|
||||
return array(60, 20, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function basicConsumeOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_shortstr();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicCancel($consumer_tag, $nowait = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_shortstr($consumer_tag);
|
||||
$args->write_bits(array($nowait));
|
||||
return array(60, 30, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function basicCancelOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_shortstr();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicPublish($ticket = 0, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($exchange);
|
||||
$args->write_shortstr($routing_key);
|
||||
$args->write_bits(array($mandatory, $immediate));
|
||||
return array(60, 40, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicReturn($reply_code, $reply_text = '', $exchange, $routing_key)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($reply_code);
|
||||
$args->write_shortstr($reply_text);
|
||||
$args->write_shortstr($exchange);
|
||||
$args->write_shortstr($routing_key);
|
||||
return array(60, 50, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicDeliver($consumer_tag, $delivery_tag, $redelivered = false, $exchange, $routing_key)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_shortstr($consumer_tag);
|
||||
$args->write_longlong($delivery_tag);
|
||||
$args->write_bits(array($redelivered));
|
||||
$args->write_shortstr($exchange);
|
||||
$args->write_shortstr($routing_key);
|
||||
return array(60, 60, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicGet($ticket = 0, $queue = '', $no_ack = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_short($ticket);
|
||||
$args->write_shortstr($queue);
|
||||
$args->write_bits(array($no_ack));
|
||||
return array(60, 70, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function basicGetOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_longlong();
|
||||
$ret[] = $args->read_bit();
|
||||
$ret[] = $args->read_shortstr();
|
||||
$ret[] = $args->read_shortstr();
|
||||
$ret[] = $args->read_long();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function basicGetEmpty($args)
|
||||
{
|
||||
$ret = array();
|
||||
$ret[] = $args->read_shortstr();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicAck($delivery_tag = 0, $multiple = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_longlong($delivery_tag);
|
||||
$args->write_bits(array($multiple));
|
||||
return array(60, 80, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicReject($delivery_tag, $requeue = true)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_longlong($delivery_tag);
|
||||
$args->write_bits(array($requeue));
|
||||
return array(60, 90, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicRecoverAsync($requeue = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_bits(array($requeue));
|
||||
return array(60, 100, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicRecover($requeue = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_bits(array($requeue));
|
||||
return array(60, 110, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function basicRecoverOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function basicNack($delivery_tag = 0, $multiple = false, $requeue = true)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_longlong($delivery_tag);
|
||||
$args->write_bits(array($multiple, $requeue));
|
||||
return array(60, 120, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function txSelect()
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
return array(90, 10, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function txSelectOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function txCommit()
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
return array(90, 20, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function txCommitOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function txRollback()
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
return array(90, 30, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function txRollbackOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function confirmSelect($nowait = false)
|
||||
{
|
||||
$args = new AMQPWriter();
|
||||
$args->write_bits(array($nowait));
|
||||
return array(85, 10, $args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param AMQPReader $args
|
||||
* @return array
|
||||
*/
|
||||
public static function confirmSelectOk($args)
|
||||
{
|
||||
$ret = array();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
113
lib/PhpAmqpLib/Helper/Protocol/Wait080.php
Normal file
113
lib/PhpAmqpLib/Helper/Protocol/Wait080.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
/* This file was autogenerated by spec/parser.php - Do not modify */
|
||||
|
||||
namespace PhpAmqpLib\Helper\Protocol;
|
||||
|
||||
class Wait080
|
||||
{
|
||||
|
||||
protected $wait = array(
|
||||
'connection.start' => '10,10',
|
||||
'connection.start_ok' => '10,11',
|
||||
'connection.secure' => '10,20',
|
||||
'connection.secure_ok' => '10,21',
|
||||
'connection.tune' => '10,30',
|
||||
'connection.tune_ok' => '10,31',
|
||||
'connection.open' => '10,40',
|
||||
'connection.open_ok' => '10,41',
|
||||
'connection.redirect' => '10,50',
|
||||
'connection.close' => '10,60',
|
||||
'connection.close_ok' => '10,61',
|
||||
'channel.open' => '20,10',
|
||||
'channel.open_ok' => '20,11',
|
||||
'channel.flow' => '20,20',
|
||||
'channel.flow_ok' => '20,21',
|
||||
'channel.alert' => '20,30',
|
||||
'channel.close' => '20,40',
|
||||
'channel.close_ok' => '20,41',
|
||||
'access.request' => '30,10',
|
||||
'access.request_ok' => '30,11',
|
||||
'exchange.declare' => '40,10',
|
||||
'exchange.declare_ok' => '40,11',
|
||||
'exchange.delete' => '40,20',
|
||||
'exchange.delete_ok' => '40,21',
|
||||
'queue.declare' => '50,10',
|
||||
'queue.declare_ok' => '50,11',
|
||||
'queue.bind' => '50,20',
|
||||
'queue.bind_ok' => '50,21',
|
||||
'queue.purge' => '50,30',
|
||||
'queue.purge_ok' => '50,31',
|
||||
'queue.delete' => '50,40',
|
||||
'queue.delete_ok' => '50,41',
|
||||
'queue.unbind' => '50,50',
|
||||
'queue.unbind_ok' => '50,51',
|
||||
'basic.qos' => '60,10',
|
||||
'basic.qos_ok' => '60,11',
|
||||
'basic.consume' => '60,20',
|
||||
'basic.consume_ok' => '60,21',
|
||||
'basic.cancel' => '60,30',
|
||||
'basic.cancel_ok' => '60,31',
|
||||
'basic.publish' => '60,40',
|
||||
'basic.return' => '60,50',
|
||||
'basic.deliver' => '60,60',
|
||||
'basic.get' => '60,70',
|
||||
'basic.get_ok' => '60,71',
|
||||
'basic.get_empty' => '60,72',
|
||||
'basic.ack' => '60,80',
|
||||
'basic.reject' => '60,90',
|
||||
'basic.recover_async' => '60,100',
|
||||
'basic.recover' => '60,110',
|
||||
'basic.recover_ok' => '60,111',
|
||||
'file.qos' => '70,10',
|
||||
'file.qos_ok' => '70,11',
|
||||
'file.consume' => '70,20',
|
||||
'file.consume_ok' => '70,21',
|
||||
'file.cancel' => '70,30',
|
||||
'file.cancel_ok' => '70,31',
|
||||
'file.open' => '70,40',
|
||||
'file.open_ok' => '70,41',
|
||||
'file.stage' => '70,50',
|
||||
'file.publish' => '70,60',
|
||||
'file.return' => '70,70',
|
||||
'file.deliver' => '70,80',
|
||||
'file.ack' => '70,90',
|
||||
'file.reject' => '70,100',
|
||||
'stream.qos' => '80,10',
|
||||
'stream.qos_ok' => '80,11',
|
||||
'stream.consume' => '80,20',
|
||||
'stream.consume_ok' => '80,21',
|
||||
'stream.cancel' => '80,30',
|
||||
'stream.cancel_ok' => '80,31',
|
||||
'stream.publish' => '80,40',
|
||||
'stream.return' => '80,50',
|
||||
'stream.deliver' => '80,60',
|
||||
'tx.select' => '90,10',
|
||||
'tx.select_ok' => '90,11',
|
||||
'tx.commit' => '90,20',
|
||||
'tx.commit_ok' => '90,21',
|
||||
'tx.rollback' => '90,30',
|
||||
'tx.rollback_ok' => '90,31',
|
||||
'dtx.select' => '100,10',
|
||||
'dtx.select_ok' => '100,11',
|
||||
'dtx.start' => '100,20',
|
||||
'dtx.start_ok' => '100,21',
|
||||
'tunnel.request' => '110,10',
|
||||
'test.integer' => '120,10',
|
||||
'test.integer_ok' => '120,11',
|
||||
'test.string' => '120,20',
|
||||
'test.string_ok' => '120,21',
|
||||
'test.table' => '120,30',
|
||||
'test.table_ok' => '120,31',
|
||||
'test.content' => '120,40',
|
||||
'test.content_ok' => '120,41',
|
||||
);
|
||||
|
||||
|
||||
|
||||
public function get_wait($method)
|
||||
{
|
||||
return $this->wait[$method];
|
||||
}
|
||||
|
||||
}
|
||||
84
lib/PhpAmqpLib/Helper/Protocol/Wait091.php
Normal file
84
lib/PhpAmqpLib/Helper/Protocol/Wait091.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/* This file was autogenerated by spec/parser.php - Do not modify */
|
||||
|
||||
namespace PhpAmqpLib\Helper\Protocol;
|
||||
|
||||
class Wait091
|
||||
{
|
||||
|
||||
protected $wait = array(
|
||||
'connection.start' => '10,10',
|
||||
'connection.start_ok' => '10,11',
|
||||
'connection.secure' => '10,20',
|
||||
'connection.secure_ok' => '10,21',
|
||||
'connection.tune' => '10,30',
|
||||
'connection.tune_ok' => '10,31',
|
||||
'connection.open' => '10,40',
|
||||
'connection.open_ok' => '10,41',
|
||||
'connection.close' => '10,50',
|
||||
'connection.close_ok' => '10,51',
|
||||
'connection.blocked' => '10,60',
|
||||
'connection.unblocked' => '10,61',
|
||||
'channel.open' => '20,10',
|
||||
'channel.open_ok' => '20,11',
|
||||
'channel.flow' => '20,20',
|
||||
'channel.flow_ok' => '20,21',
|
||||
'channel.close' => '20,40',
|
||||
'channel.close_ok' => '20,41',
|
||||
'access.request' => '30,10',
|
||||
'access.request_ok' => '30,11',
|
||||
'exchange.declare' => '40,10',
|
||||
'exchange.declare_ok' => '40,11',
|
||||
'exchange.delete' => '40,20',
|
||||
'exchange.delete_ok' => '40,21',
|
||||
'exchange.bind' => '40,30',
|
||||
'exchange.bind_ok' => '40,31',
|
||||
'exchange.unbind' => '40,40',
|
||||
'exchange.unbind_ok' => '40,51',
|
||||
'queue.declare' => '50,10',
|
||||
'queue.declare_ok' => '50,11',
|
||||
'queue.bind' => '50,20',
|
||||
'queue.bind_ok' => '50,21',
|
||||
'queue.purge' => '50,30',
|
||||
'queue.purge_ok' => '50,31',
|
||||
'queue.delete' => '50,40',
|
||||
'queue.delete_ok' => '50,41',
|
||||
'queue.unbind' => '50,50',
|
||||
'queue.unbind_ok' => '50,51',
|
||||
'basic.qos' => '60,10',
|
||||
'basic.qos_ok' => '60,11',
|
||||
'basic.consume' => '60,20',
|
||||
'basic.consume_ok' => '60,21',
|
||||
'basic.cancel' => '60,30',
|
||||
'basic.cancel_ok' => '60,31',
|
||||
'basic.publish' => '60,40',
|
||||
'basic.return' => '60,50',
|
||||
'basic.deliver' => '60,60',
|
||||
'basic.get' => '60,70',
|
||||
'basic.get_ok' => '60,71',
|
||||
'basic.get_empty' => '60,72',
|
||||
'basic.ack' => '60,80',
|
||||
'basic.reject' => '60,90',
|
||||
'basic.recover_async' => '60,100',
|
||||
'basic.recover' => '60,110',
|
||||
'basic.recover_ok' => '60,111',
|
||||
'basic.nack' => '60,120',
|
||||
'tx.select' => '90,10',
|
||||
'tx.select_ok' => '90,11',
|
||||
'tx.commit' => '90,20',
|
||||
'tx.commit_ok' => '90,21',
|
||||
'tx.rollback' => '90,30',
|
||||
'tx.rollback_ok' => '90,31',
|
||||
'confirm.select' => '85,10',
|
||||
'confirm.select_ok' => '85,11',
|
||||
);
|
||||
|
||||
|
||||
|
||||
public function get_wait($method)
|
||||
{
|
||||
return $this->wait[$method];
|
||||
}
|
||||
|
||||
}
|
||||
57
lib/PhpAmqpLib/Message/AMQPMessage.php
Normal file
57
lib/PhpAmqpLib/Message/AMQPMessage.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Message;
|
||||
|
||||
use PhpAmqpLib\Wire\GenericContent;
|
||||
|
||||
/**
|
||||
* A Message for use with the Channnel.basic_* methods.
|
||||
*/
|
||||
class AMQPMessage extends GenericContent
|
||||
{
|
||||
/** @var string */
|
||||
public $body;
|
||||
public $body_size;
|
||||
public $is_truncated = false;
|
||||
|
||||
/** @var string */
|
||||
public $content_encoding;
|
||||
|
||||
/** @var array */
|
||||
protected static $propertyDefinitions = array(
|
||||
'content_type' => 'shortstr',
|
||||
'content_encoding' => 'shortstr',
|
||||
'application_headers' => 'table_object',
|
||||
'delivery_mode' => 'octet',
|
||||
'priority' => 'octet',
|
||||
'correlation_id' => 'shortstr',
|
||||
'reply_to' => 'shortstr',
|
||||
'expiration' => 'shortstr',
|
||||
'message_id' => 'shortstr',
|
||||
'timestamp' => 'timestamp',
|
||||
'type' => 'shortstr',
|
||||
'user_id' => 'shortstr',
|
||||
'app_id' => 'shortstr',
|
||||
'cluster_id' => 'shortstr',
|
||||
);
|
||||
|
||||
/**
|
||||
* @param string $body
|
||||
* @param null $properties
|
||||
*/
|
||||
public function __construct($body = '', $properties = null)
|
||||
{
|
||||
$this->setBody($body);
|
||||
parent::__construct($properties, static::$propertyDefinitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the message payload
|
||||
*
|
||||
* @param mixed $body
|
||||
* @return $this
|
||||
*/
|
||||
public function setBody($body)
|
||||
{
|
||||
$this->body = $body;
|
||||
}
|
||||
}
|
||||
446
lib/PhpAmqpLib/Wire/AMQPAbstractCollection.php
Normal file
446
lib/PhpAmqpLib/Wire/AMQPAbstractCollection.php
Normal file
@@ -0,0 +1,446 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire;
|
||||
|
||||
use PhpAmqpLib\Channel\AbstractChannel;
|
||||
use PhpAmqpLib\Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Iterator implemented for transparent integration with AMQPWriter::write_[array|table]()
|
||||
*/
|
||||
abstract class AMQPAbstractCollection implements \Iterator
|
||||
{
|
||||
|
||||
//protocol defines available field types and their corresponding symbols
|
||||
const PROTOCOL_080 = AbstractChannel::PROTOCOL_080;
|
||||
const PROTOCOL_091 = AbstractChannel::PROTOCOL_091;
|
||||
const PROTOCOL_RBT = 'rabbit'; //pseudo proto
|
||||
|
||||
//Abstract data types
|
||||
const T_INT_SHORTSHORT = 1;
|
||||
const T_INT_SHORTSHORT_U = 2;
|
||||
const T_INT_SHORT = 3;
|
||||
const T_INT_SHORT_U = 4;
|
||||
const T_INT_LONG = 5;
|
||||
const T_INT_LONG_U = 6;
|
||||
const T_INT_LONGLONG = 7;
|
||||
const T_INT_LONGLONG_U = 8;
|
||||
|
||||
const T_DECIMAL = 9;
|
||||
const T_TIMESTAMP = 10;
|
||||
const T_VOID = 11;
|
||||
|
||||
const T_BOOL = 12;
|
||||
|
||||
const T_STRING_SHORT = 13;
|
||||
const T_STRING_LONG = 14;
|
||||
|
||||
const T_ARRAY = 15;
|
||||
const T_TABLE = 16;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $_protocol = null;
|
||||
|
||||
/*
|
||||
* Field types messy mess http://www.rabbitmq.com/amqp-0-9-1-errata.html#section_3
|
||||
* Default behaviour is to use rabbitMQ compatible field-set
|
||||
* Define AMQP_STRICT_FLD_TYPES=true to use strict AMQP instead
|
||||
*/
|
||||
private static $_types_080 = array(
|
||||
self::T_INT_LONG => 'I',
|
||||
self::T_DECIMAL => 'D',
|
||||
self::T_TIMESTAMP => 'T',
|
||||
self::T_STRING_LONG => 'S',
|
||||
self::T_TABLE => 'F'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $_types_091 = array(
|
||||
self::T_INT_SHORTSHORT => 'b',
|
||||
self::T_INT_SHORTSHORT_U => 'B',
|
||||
self::T_INT_SHORT => 'U',
|
||||
self::T_INT_SHORT_U => 'u',
|
||||
self::T_INT_LONG => 'I',
|
||||
self::T_INT_LONG_U => 'i',
|
||||
self::T_INT_LONGLONG => 'L',
|
||||
self::T_INT_LONGLONG_U => 'l',
|
||||
self::T_DECIMAL => 'D',
|
||||
self::T_TIMESTAMP => 'T',
|
||||
self::T_VOID => 'V',
|
||||
self::T_BOOL => 't',
|
||||
self::T_STRING_SHORT => 's',
|
||||
self::T_STRING_LONG => 'S',
|
||||
self::T_ARRAY => 'A',
|
||||
self::T_TABLE => 'F'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $_types_rabbit = array(
|
||||
self::T_INT_SHORTSHORT => 'b',
|
||||
self::T_INT_SHORT => 's',
|
||||
self::T_INT_LONG => 'I',
|
||||
self::T_INT_LONGLONG => 'l',
|
||||
self::T_DECIMAL => 'D',
|
||||
self::T_TIMESTAMP => 'T',
|
||||
self::T_VOID => 'V',
|
||||
self::T_BOOL => 't',
|
||||
self::T_STRING_LONG => 'S',
|
||||
self::T_ARRAY => 'A',
|
||||
self::T_TABLE => 'F'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data = array();
|
||||
|
||||
public function __construct(array $data = null)
|
||||
{
|
||||
if (!empty($data)) {
|
||||
$this->data = $this->encodeCollection($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
abstract public function getType();
|
||||
|
||||
/**
|
||||
* @param mixed $val
|
||||
* @param int $type
|
||||
* @param string $key
|
||||
*/
|
||||
final protected function setValue($val, $type = null, $key = null)
|
||||
{
|
||||
if ($val instanceof self) {
|
||||
if ($type && ($type != $val->getType())) {
|
||||
throw new Exception\AMQPInvalidArgumentException(
|
||||
'Attempted to add instance of ' . get_class($val) . ' representing type [' . $val->getType() . '] as mismatching type [' . $type . ']'
|
||||
);
|
||||
}
|
||||
$type = $val->getType();
|
||||
} elseif ($type) { //ensuring data integrity and that all members are properly validated
|
||||
switch ($type) {
|
||||
case self::T_ARRAY:
|
||||
throw new Exception\AMQPInvalidArgumentException('Arrays must be passed as AMQPArray instance');
|
||||
break;
|
||||
case self::T_TABLE:
|
||||
throw new Exception\AMQPInvalidArgumentException('Tables must be passed as AMQPTable instance');
|
||||
break;
|
||||
case self::T_DECIMAL:
|
||||
if (!($val instanceof AMQPDecimal)) {
|
||||
throw new Exception\AMQPInvalidArgumentException('Decimal values must be instance of AMQPDecimal');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($type) {
|
||||
self::checkDataTypeIsSupported($type, false);
|
||||
$val = array($type, $val);
|
||||
} else {
|
||||
$val = $this->encodeValue($val);
|
||||
}
|
||||
|
||||
if ($key === null) {
|
||||
$this->data[] = $val;
|
||||
} else {
|
||||
$this->data[$key] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
final public function getNativeData()
|
||||
{
|
||||
return $this->decodeCollection($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $val
|
||||
* @return array
|
||||
*/
|
||||
final protected function encodeCollection(array $val)
|
||||
{
|
||||
foreach ($val as &$v) {
|
||||
$v = $this->encodeValue($v);
|
||||
}
|
||||
unset($v);
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $val
|
||||
* @return array
|
||||
*/
|
||||
final protected function decodeCollection(array $val)
|
||||
{
|
||||
foreach ($val as &$v) {
|
||||
$v = $this->decodeValue($v[1], $v[0]);
|
||||
}
|
||||
unset($v);
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $val
|
||||
* @return mixed
|
||||
* @throws Exception\AMQPOutOfBoundsException
|
||||
*/
|
||||
protected function encodeValue($val)
|
||||
{
|
||||
if (is_string($val)) {
|
||||
$val = $this->encodeString($val);
|
||||
} elseif (is_float($val)) {
|
||||
$val = $this->encodeFloat($val);
|
||||
} elseif (is_int($val)) {
|
||||
$val = $this->encodeInt($val);
|
||||
} elseif (is_bool($val)) {
|
||||
$val = $this->encodeBool($val);
|
||||
} elseif (is_null($val)) {
|
||||
$val = $this->encodeVoid();
|
||||
} elseif ($val instanceof \DateTime) {
|
||||
$val = array(self::T_TIMESTAMP, $val->getTimestamp());
|
||||
} elseif ($val instanceof AMQPDecimal) {
|
||||
$val = array(self::T_DECIMAL, $val);
|
||||
} elseif ($val instanceof self) {
|
||||
//avoid silent type correction of strictly typed values
|
||||
self::checkDataTypeIsSupported($val->getType(), false);
|
||||
$val = array($val->getType(), $val);
|
||||
} elseif (is_array($val)) {
|
||||
//AMQP specs says "Field names MUST start with a letter, '$' or '#'"
|
||||
//so beware, some servers may raise an exception with 503 code in cases when indexed array is encoded as table
|
||||
if (self::isProtocol(self::PROTOCOL_080)) {
|
||||
//080 doesn't support arrays, forcing table
|
||||
$val = array(self::T_TABLE, new AMQPTable($val));
|
||||
} elseif (empty($val) || (array_keys($val) === range(0, count($val) - 1))) {
|
||||
$val = array(self::T_ARRAY, new AMQPArray($val));
|
||||
} else {
|
||||
$val = array(self::T_TABLE, new AMQPTable($val));
|
||||
}
|
||||
} else {
|
||||
throw new Exception\AMQPOutOfBoundsException(sprintf('Encountered value of unsupported type: %s', gettype($val)));
|
||||
}
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $val
|
||||
* @param integer $type
|
||||
* @return array|bool|\DateTime|null
|
||||
*/
|
||||
protected function decodeValue($val, $type)
|
||||
{
|
||||
if ($val instanceof self) {
|
||||
//covering arrays and tables
|
||||
$val = $val->getNativeData();
|
||||
} else {
|
||||
switch ($type) {
|
||||
case self::T_BOOL:
|
||||
$val = (bool) $val;
|
||||
break;
|
||||
case self::T_TIMESTAMP:
|
||||
$val = \DateTime::createFromFormat('U', $val);
|
||||
break;
|
||||
case self::T_VOID:
|
||||
$val = null;
|
||||
break;
|
||||
case self::T_ARRAY:
|
||||
case self::T_TABLE:
|
||||
throw new Exception\AMQPLogicException(
|
||||
'Encountered an array/table struct which is not an instance of AMQPCollection. ' .
|
||||
'This is considered a bug and should be fixed, please report'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $val
|
||||
* @return array
|
||||
*/
|
||||
protected function encodeString($val)
|
||||
{
|
||||
return array(self::T_STRING_LONG, $val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $val
|
||||
* @return array
|
||||
*/
|
||||
protected function encodeInt($val)
|
||||
{
|
||||
if (($val >= -2147483648) && ($val <= 2147483647)) {
|
||||
$ev = array(self::T_INT_LONG, $val);
|
||||
} elseif (self::isProtocol(self::PROTOCOL_080)) {
|
||||
//080 doesn't support longlong
|
||||
$ev = $this->encodeString((string) $val);
|
||||
} else {
|
||||
$ev = array(self::T_INT_LONGLONG, $val);
|
||||
}
|
||||
|
||||
return $ev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $val
|
||||
* @return array
|
||||
*/
|
||||
protected function encodeFloat($val)
|
||||
{
|
||||
return static::encodeString((string) $val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $val
|
||||
* @return array
|
||||
*/
|
||||
protected function encodeBool($val)
|
||||
{
|
||||
$val = (bool) $val;
|
||||
|
||||
return self::isProtocol(self::PROTOCOL_080) ? array(self::T_INT_LONG, (int) $val) : array(self::T_BOOL, $val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function encodeVoid()
|
||||
{
|
||||
return self::isProtocol(self::PROTOCOL_080) ? $this->encodeString('') : array(self::T_VOID, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
final public static function getProtocol()
|
||||
{
|
||||
if (self::$_protocol === null) {
|
||||
self::$_protocol = defined('AMQP_STRICT_FLD_TYPES') && AMQP_STRICT_FLD_TYPES ?
|
||||
AbstractChannel::getProtocolVersion() :
|
||||
self::PROTOCOL_RBT;
|
||||
}
|
||||
|
||||
return self::$_protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $proto
|
||||
* @return bool
|
||||
*/
|
||||
final public static function isProtocol($proto)
|
||||
{
|
||||
return self::getProtocol() == $proto;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array [dataTypeConstant => dataTypeSymbol]
|
||||
*/
|
||||
final public static function getSupportedDataTypes()
|
||||
{
|
||||
switch ($proto = self::getProtocol()) {
|
||||
case self::PROTOCOL_080:
|
||||
$types = self::$_types_080;
|
||||
break;
|
||||
case self::PROTOCOL_091:
|
||||
$types = self::$_types_091;
|
||||
break;
|
||||
case self::PROTOCOL_RBT:
|
||||
$types = self::$_types_rabbit;
|
||||
break;
|
||||
default:
|
||||
throw new Exception\AMQPOutOfRangeException(sprintf('Unknown protocol: %s', $proto));
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param bool $return Whether to return or raise AMQPOutOfRangeException
|
||||
* @return boolean
|
||||
*/
|
||||
final public static function checkDataTypeIsSupported($type, $return = true)
|
||||
{
|
||||
try {
|
||||
$supported = self::getSupportedDataTypes();
|
||||
if (!isset($supported[$type])) {
|
||||
throw new Exception\AMQPOutOfRangeException(sprintf('AMQP-%s doesn\'t support data of type [%s]', self::getProtocol(), $type));
|
||||
}
|
||||
return true;
|
||||
|
||||
} catch (Exception\AMQPOutOfRangeException $ex) {
|
||||
if (!$return) {
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $type
|
||||
* @return string
|
||||
*/
|
||||
final public static function getSymbolForDataType($type)
|
||||
{
|
||||
$types = self::getSupportedDataTypes();
|
||||
if (!isset($types[$type])) {
|
||||
throw new Exception\AMQPOutOfRangeException(sprintf('AMQP-%s doesn\'t support data of type [%s]', self::getProtocol(), $type));
|
||||
}
|
||||
|
||||
return $types[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $symbol
|
||||
* @return integer
|
||||
*/
|
||||
final public static function getDataTypeForSymbol($symbol)
|
||||
{
|
||||
$symbols = array_flip(self::getSupportedDataTypes());
|
||||
if (!isset($symbols[$symbol])) {
|
||||
throw new Exception\AMQPOutOfRangeException(sprintf('AMQP-%s doesn\'t define data of type [%s]', self::getProtocol(), $symbol));
|
||||
}
|
||||
|
||||
return $symbols[$symbol];
|
||||
}
|
||||
|
||||
public function current()
|
||||
{
|
||||
return current($this->data);
|
||||
}
|
||||
|
||||
public function key()
|
||||
{
|
||||
return key($this->data);
|
||||
}
|
||||
|
||||
public function next()
|
||||
{
|
||||
next($this->data);
|
||||
}
|
||||
|
||||
public function rewind()
|
||||
{
|
||||
reset($this->data);
|
||||
}
|
||||
|
||||
public function valid()
|
||||
{
|
||||
return key($this->data) !== null;
|
||||
}
|
||||
}
|
||||
32
lib/PhpAmqpLib/Wire/AMQPArray.php
Normal file
32
lib/PhpAmqpLib/Wire/AMQPArray.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire;
|
||||
|
||||
|
||||
class AMQPArray extends AMQPAbstractCollection
|
||||
{
|
||||
|
||||
public function __construct(array $data = null)
|
||||
{
|
||||
parent::__construct(empty($data) ? null : array_values($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
final public function getType()
|
||||
{
|
||||
return self::T_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $val
|
||||
* @param null $type
|
||||
* @return $this
|
||||
*/
|
||||
public function push($val, $type = null)
|
||||
{
|
||||
$this->setValue($val, $type);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
47
lib/PhpAmqpLib/Wire/AMQPDecimal.php
Normal file
47
lib/PhpAmqpLib/Wire/AMQPDecimal.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire;
|
||||
|
||||
use PhpAmqpLib\Exception\AMQPOutOfBoundsException;
|
||||
|
||||
/**
|
||||
* AMQP protocol decimal value.
|
||||
*
|
||||
* Values are represented as (n,e) pairs. The actual value
|
||||
* is n * 10^(-e).
|
||||
*
|
||||
* From 0.8 spec: Decimal values are
|
||||
* not intended to support floating point values, but rather
|
||||
* business values such as currency rates and amounts. The
|
||||
* 'decimals' octet is not signed.
|
||||
*/
|
||||
class AMQPDecimal
|
||||
{
|
||||
/** @var int */
|
||||
protected $n;
|
||||
|
||||
/** @var int */
|
||||
protected $e;
|
||||
|
||||
/**
|
||||
* @param $n
|
||||
* @param $e
|
||||
* @throws \PhpAmqpLib\Exception\AMQPOutOfBoundsException
|
||||
*/
|
||||
public function __construct($n, $e)
|
||||
{
|
||||
if ($e < 0) {
|
||||
throw new AMQPOutOfBoundsException('Decimal exponent value must be unsigned!');
|
||||
}
|
||||
|
||||
$this->n = $n;
|
||||
$this->e = $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function asBCvalue()
|
||||
{
|
||||
return bcdiv($this->n, bcpow(10, $this->e));
|
||||
}
|
||||
}
|
||||
534
lib/PhpAmqpLib/Wire/AMQPReader.php
Normal file
534
lib/PhpAmqpLib/Wire/AMQPReader.php
Normal file
@@ -0,0 +1,534 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire;
|
||||
|
||||
use PhpAmqpLib\Exception\AMQPInvalidArgumentException;
|
||||
use PhpAmqpLib\Exception\AMQPOutOfBoundsException;
|
||||
use PhpAmqpLib\Exception\AMQPRuntimeException;
|
||||
use PhpAmqpLib\Exception\AMQPTimeoutException;
|
||||
use PhpAmqpLib\Helper\MiscHelper;
|
||||
use PhpAmqpLib\Wire\IO\AbstractIO;
|
||||
|
||||
/**
|
||||
* This class can read from a string or from a stream
|
||||
*
|
||||
* TODO : split this class: AMQPStreamReader and a AMQPBufferReader
|
||||
*/
|
||||
class AMQPReader extends AbstractClient
|
||||
{
|
||||
const BIT = 1;
|
||||
const OCTET = 1;
|
||||
const SHORTSTR = 1;
|
||||
const SHORT = 2;
|
||||
const LONG = 4;
|
||||
const SIGNED_LONG = 4;
|
||||
const READ_PHP_INT = 4; // use READ_ to avoid possible clashes with PHP
|
||||
const LONGLONG = 8;
|
||||
const TIMESTAMP = 8;
|
||||
|
||||
/** @var string */
|
||||
protected $str;
|
||||
|
||||
/** @var int */
|
||||
protected $str_length;
|
||||
|
||||
/** @var int */
|
||||
protected $offset;
|
||||
|
||||
/** @var int */
|
||||
protected $bitcount;
|
||||
|
||||
/** @var bool */
|
||||
protected $is64bits;
|
||||
|
||||
/** @var int */
|
||||
protected $timeout;
|
||||
|
||||
/** @var int */
|
||||
protected $bits;
|
||||
|
||||
/** @var \PhpAmqpLib\Wire\IO\AbstractIO */
|
||||
protected $io;
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param AbstractIO $io
|
||||
* @param int $timeout
|
||||
*/
|
||||
public function __construct($str, AbstractIO $io = null, $timeout = 0)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->str = $str;
|
||||
$this->str_length = mb_strlen($this->str, 'ASCII');
|
||||
$this->io = $io;
|
||||
$this->offset = 0;
|
||||
$this->bitcount = $this->bits = 0;
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the object from the injected param
|
||||
*
|
||||
* Used to not need to create a new AMQPReader instance every time.
|
||||
* when we can just pass a string and reset the object state.
|
||||
* NOTE: since we are working with strings we don't need to pass an AbstractIO
|
||||
* or a timeout.
|
||||
*
|
||||
* @param string $str
|
||||
*/
|
||||
public function reuse($str)
|
||||
{
|
||||
$this->str = $str;
|
||||
$this->str_length = mb_strlen($this->str, 'ASCII');
|
||||
$this->offset = 0;
|
||||
$this->bitcount = $this->bits = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the stream
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
if ($this->io) {
|
||||
$this->io->close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $n
|
||||
* @return string
|
||||
*/
|
||||
public function read($n)
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
|
||||
return $this->rawread($n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until some data is retrieved from the socket.
|
||||
*
|
||||
* AMQPTimeoutException can be raised if the timeout is set
|
||||
*
|
||||
* @throws \PhpAmqpLib\Exception\AMQPTimeoutException
|
||||
*/
|
||||
protected function wait()
|
||||
{
|
||||
if ($this->timeout == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// wait ..
|
||||
list($sec, $usec) = MiscHelper::splitSecondsMicroseconds($this->timeout);
|
||||
$result = $this->io->select($sec, $usec);
|
||||
|
||||
if ($result === false) {
|
||||
throw new AMQPRuntimeException('A network error occured while awaiting for incoming data');
|
||||
}
|
||||
|
||||
if ($result === 0) {
|
||||
throw new AMQPTimeoutException(sprintf(
|
||||
'The connection timed out after %s sec while awaiting incoming data',
|
||||
$this->getTimeout()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $n
|
||||
* @return string
|
||||
* @throws \RuntimeException
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
*/
|
||||
protected function rawread($n)
|
||||
{
|
||||
if ($this->io) {
|
||||
$this->wait();
|
||||
$res = $this->io->read($n);
|
||||
$this->offset += $n;
|
||||
} else {
|
||||
if ($this->str_length < $n) {
|
||||
throw new AMQPRuntimeException(sprintf(
|
||||
'Error reading data. Requested %s bytes while string buffer has only %s',
|
||||
$n,
|
||||
$this->str_length
|
||||
));
|
||||
}
|
||||
|
||||
$res = mb_substr($this->str, 0, $n, 'ASCII');
|
||||
$this->str = mb_substr($this->str, $n, mb_strlen($this->str, 'ASCII') - $n, 'ASCII');
|
||||
$this->str_length -= $n;
|
||||
$this->offset += $n;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function read_bit()
|
||||
{
|
||||
if (!$this->bitcount) {
|
||||
$this->bits = ord($this->rawread(1));
|
||||
$this->bitcount = 8;
|
||||
}
|
||||
|
||||
$result = ($this->bits & 1) == 1;
|
||||
$this->bits >>= 1;
|
||||
$this->bitcount -= 1;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function read_octet()
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
list(, $res) = unpack('C', $this->rawread(1));
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function read_signed_octet()
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
list(, $res) = unpack('c', $this->rawread(1));
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function read_short()
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
list(, $res) = unpack('n', $this->rawread(2));
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function read_signed_short()
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
list(, $res) = unpack('s', $this->correctEndianness($this->rawread(2)));
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads 32 bit integer in big-endian byte order.
|
||||
*
|
||||
* On 64 bit systems it will return always unsigned int
|
||||
* value in 0..2^32 range.
|
||||
*
|
||||
* On 32 bit systems it will return signed int value in
|
||||
* -2^31...+2^31 range.
|
||||
*
|
||||
* Use with caution!
|
||||
*/
|
||||
public function read_php_int()
|
||||
{
|
||||
list(, $res) = unpack('N', $this->rawread(4));
|
||||
if ($this->is64bits) {
|
||||
$sres = sprintf('%u', $res);
|
||||
return (int) $sres;
|
||||
} else {
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP does not have unsigned 32 bit int,
|
||||
* so we return it as a string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function read_long()
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
list(, $res) = unpack('N', $this->rawread(4));
|
||||
|
||||
return !$this->is64bits && self::getLongMSB($res) ? sprintf('%u', $res) : $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
private function read_signed_long()
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
list(, $res) = unpack('l', $this->correctEndianness($this->rawread(4)));
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Even on 64 bit systems PHP integers are singed.
|
||||
* Since we need an unsigned value here we return it
|
||||
* as a string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function read_longlong()
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
|
||||
list(, $hi, $lo) = unpack('N2', $this->rawread(8));
|
||||
$msb = self::getLongMSB($hi);
|
||||
|
||||
if (!$this->is64bits) {
|
||||
if ($msb) {
|
||||
$hi = sprintf('%u', $hi);
|
||||
}
|
||||
if (self::getLongMSB($lo)) {
|
||||
$lo = sprintf('%u', $lo);
|
||||
}
|
||||
}
|
||||
|
||||
return bcadd($this->is64bits && !$msb ? $hi << 32 : bcmul($hi, '4294967296', 0), $lo, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function read_signed_longlong()
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
|
||||
list(, $hi, $lo) = unpack('N2', $this->rawread(8));
|
||||
|
||||
if ($this->is64bits) {
|
||||
return bcadd($hi << 32, $lo, 0);
|
||||
} else {
|
||||
return bcadd(bcmul($hi, '4294967296', 0), self::getLongMSB($lo) ? sprintf('%u', $lo) : $lo, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $longInt
|
||||
* @return bool
|
||||
*/
|
||||
private static function getLongMSB($longInt)
|
||||
{
|
||||
return (bool) ($longInt & 0x80000000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a utf-8 encoded string that's stored in up to
|
||||
* 255 bytes. Return it decoded as a PHP unicode object.
|
||||
*/
|
||||
public function read_shortstr()
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
list(, $slen) = unpack('C', $this->rawread(1));
|
||||
|
||||
return $this->rawread($slen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a string that's up to 2**32 bytes, the encoding
|
||||
* isn't specified in the AMQP spec, so just return it as
|
||||
* a plain PHP string.
|
||||
*/
|
||||
public function read_longstr()
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
$slen = $this->read_php_int();
|
||||
|
||||
if ($slen < 0) {
|
||||
throw new AMQPOutOfBoundsException('Strings longer than supported on this platform');
|
||||
}
|
||||
|
||||
return $this->rawread($slen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and AMQP timestamp, which is a 64-bit integer representing
|
||||
* seconds since the Unix epoch in 1-second resolution.
|
||||
*/
|
||||
public function read_timestamp()
|
||||
{
|
||||
return $this->read_longlong();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an AMQP table, and return as a PHP array. keys are strings,
|
||||
* values are (type,value) tuples.
|
||||
*
|
||||
* @param bool $returnObject Whether to return AMQPArray instance instead of plain array
|
||||
* @return array|AMQPTable
|
||||
*/
|
||||
public function read_table($returnObject = false)
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
$tlen = $this->read_php_int();
|
||||
|
||||
if ($tlen < 0) {
|
||||
throw new AMQPOutOfBoundsException('Table is longer than supported');
|
||||
}
|
||||
|
||||
$table_data = new AMQPReader($this->rawread($tlen), null);
|
||||
$result = $returnObject ? new AMQPTable() : array();
|
||||
while ($table_data->tell() < $tlen) {
|
||||
$name = $table_data->read_shortstr();
|
||||
$ftype = AMQPAbstractCollection::getDataTypeForSymbol($ftypeSym = $table_data->rawread(1));
|
||||
$val = $table_data->read_value($ftype, $returnObject);
|
||||
$returnObject ? $result->set($name, $val, $ftype) : $result[$name] = array($ftypeSym, $val);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|AMQPTable
|
||||
*/
|
||||
public function read_table_object()
|
||||
{
|
||||
return $this->read_table(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the array in the next value.
|
||||
*
|
||||
* @param bool $returnObject Whether to return AMQPArray instance instead of plain array
|
||||
* @return array|AMQPArray
|
||||
*/
|
||||
public function read_array($returnObject = false)
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
|
||||
// Determine array length and its end position
|
||||
$arrayLength = $this->read_php_int();
|
||||
$endOffset = $this->offset + $arrayLength;
|
||||
|
||||
$result = $returnObject ? new AMQPArray() : array();
|
||||
// Read values until we reach the end of the array
|
||||
while ($this->offset < $endOffset) {
|
||||
$fieldType = AMQPAbstractCollection::getDataTypeForSymbol($this->rawread(1));
|
||||
$fieldValue = $this->read_value($fieldType, $returnObject);
|
||||
$returnObject ? $result->push($fieldValue, $fieldType) : $result[] = $fieldValue;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|AMQPArray
|
||||
*/
|
||||
public function read_array_object()
|
||||
{
|
||||
return $this->read_array(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next value as the provided field type.
|
||||
*
|
||||
* @param int $fieldType One of AMQPAbstractCollection::T_* constants
|
||||
* @param bool $collectionsAsObjects Description
|
||||
* @return mixed
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
*/
|
||||
public function read_value($fieldType, $collectionsAsObjects = false)
|
||||
{
|
||||
$this->bitcount = $this->bits = 0;
|
||||
|
||||
$val = null;
|
||||
switch ($fieldType) {
|
||||
case AMQPAbstractCollection::T_INT_SHORTSHORT:
|
||||
//according to AMQP091 spec, 'b' is not bit, it is short-short-int, also valid for rabbit/qpid
|
||||
//$val=$this->read_bit();
|
||||
$val = $this->read_signed_octet();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_SHORTSHORT_U:
|
||||
$val = $this->read_octet();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_SHORT:
|
||||
$val = $this->read_signed_short();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_SHORT_U:
|
||||
$val = $this->read_short();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_LONG:
|
||||
$val = $this->read_signed_long();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_LONG_U:
|
||||
$val = $this->read_long();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_LONGLONG:
|
||||
$val = $this->read_signed_longlong();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_LONGLONG_U:
|
||||
$val = $this->read_longlong();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_DECIMAL:
|
||||
$e = $this->read_octet();
|
||||
$n = $this->read_signed_long();
|
||||
$val = new AMQPDecimal($n, $e);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_TIMESTAMP:
|
||||
$val = $this->read_timestamp();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_BOOL:
|
||||
$val = $this->read_octet();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_STRING_SHORT:
|
||||
$val = $this->read_shortstr();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_STRING_LONG:
|
||||
$val = $this->read_longstr();
|
||||
break;
|
||||
case AMQPAbstractCollection::T_ARRAY:
|
||||
$val = $this->read_array($collectionsAsObjects);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_TABLE:
|
||||
$val = $this->read_table($collectionsAsObjects);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_VOID:
|
||||
$val = null;
|
||||
break;
|
||||
default:
|
||||
throw new AMQPInvalidArgumentException(sprintf(
|
||||
'Unsupported type "%s"',
|
||||
$fieldType
|
||||
));
|
||||
}
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
protected function tell()
|
||||
{
|
||||
return $this->offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timeout (second)
|
||||
*
|
||||
* @param $timeout
|
||||
*/
|
||||
public function setTimeout($timeout)
|
||||
{
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTimeout()
|
||||
{
|
||||
return $this->timeout;
|
||||
}
|
||||
}
|
||||
35
lib/PhpAmqpLib/Wire/AMQPTable.php
Normal file
35
lib/PhpAmqpLib/Wire/AMQPTable.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire;
|
||||
|
||||
use PhpAmqpLib\Exception;
|
||||
|
||||
|
||||
class AMQPTable extends AMQPAbstractCollection
|
||||
{
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
final public function getType()
|
||||
{
|
||||
return self::T_TABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $val
|
||||
* @param integer $type
|
||||
*/
|
||||
public function set($key, $val, $type = null)
|
||||
{
|
||||
//https://www.rabbitmq.com/resources/specs/amqp0-9-1.pdf, https://www.rabbitmq.com/resources/specs/amqp0-8.pdf
|
||||
//Field names MUST start with a letter, '$' or '#' and may continue with letters, '$' or '#', digits, or underlines, to a maximum length of 128 characters
|
||||
//The server SHOULD validate field names and upon receiving an invalid field name, it SHOULD signal a connection exception with reply code 503 (syntax error)
|
||||
|
||||
//validating length only and delegating other stuff to server, as rabbit seems to currently support numeric keys
|
||||
if (!($len = strlen($key)) || ($len > 128)) {
|
||||
throw new Exception\AMQPInvalidArgumentException('Table key must be non-empty string up to 128 chars in length');
|
||||
}
|
||||
$this->setValue($val, $type, $key);
|
||||
}
|
||||
}
|
||||
494
lib/PhpAmqpLib/Wire/AMQPWriter.php
Normal file
494
lib/PhpAmqpLib/Wire/AMQPWriter.php
Normal file
@@ -0,0 +1,494 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire;
|
||||
|
||||
use PhpAmqpLib\Exception\AMQPInvalidArgumentException;
|
||||
use PhpAmqpLib\Exception\AMQPOutOfBoundsException;
|
||||
|
||||
class AMQPWriter extends AbstractClient
|
||||
{
|
||||
/** @var string */
|
||||
protected $out;
|
||||
|
||||
/** @var array */
|
||||
protected $bits;
|
||||
|
||||
/** @var int */
|
||||
protected $bitcount;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->out = '';
|
||||
$this->bits = array();
|
||||
$this->bitcount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Packs integer into raw byte string in big-endian order
|
||||
* Supports positive and negative ints represented as PHP int or string (except scientific notation)
|
||||
*
|
||||
* Floats has some precision issues and so intentionally not supported.
|
||||
* Beware that floats out of PHP_INT_MAX range will be represented in scientific (exponential) notation when casted to string
|
||||
*
|
||||
* @param int|string $x Value to pack
|
||||
* @param int $bytes Must be multiply of 2
|
||||
* @return string
|
||||
*/
|
||||
private static function packBigEndian($x, $bytes)
|
||||
{
|
||||
if (($bytes <= 0) || ($bytes % 2)) {
|
||||
throw new AMQPInvalidArgumentException(sprintf('Expected bytes count must be multiply of 2, %s given', $bytes));
|
||||
}
|
||||
|
||||
$ox = $x; //purely for dbg purposes (overflow exception)
|
||||
$isNeg = false;
|
||||
if (is_int($x)) {
|
||||
if ($x < 0) {
|
||||
$isNeg = true;
|
||||
$x = abs($x);
|
||||
}
|
||||
} elseif (is_string($x)) {
|
||||
if (!is_numeric($x)) {
|
||||
throw new AMQPInvalidArgumentException(sprintf('Unknown numeric string format: %s', $x));
|
||||
}
|
||||
$x = preg_replace('/^-/', '', $x, 1, $isNeg);
|
||||
} else {
|
||||
throw new AMQPInvalidArgumentException('Only integer and numeric string values are supported');
|
||||
}
|
||||
if ($isNeg) {
|
||||
$x = bcadd($x, -1, 0);
|
||||
} //in negative domain starting point is -1, not 0
|
||||
|
||||
$res = array();
|
||||
for ($b = 0; $b < $bytes; $b += 2) {
|
||||
$chnk = (int) bcmod($x, 65536);
|
||||
$x = bcdiv($x, 65536, 0);
|
||||
$res[] = pack('n', $isNeg ? ~$chnk : $chnk);
|
||||
}
|
||||
if ($x || ($isNeg && ($chnk & 0x8000))) {
|
||||
throw new AMQPOutOfBoundsException(sprintf('Overflow detected while attempting to pack %s into %s bytes', $ox, $bytes));
|
||||
}
|
||||
|
||||
return implode(array_reverse($res));
|
||||
}
|
||||
|
||||
private function flushbits()
|
||||
{
|
||||
if (!empty($this->bits)) {
|
||||
$this->out .= implode('', array_map('chr', $this->bits));
|
||||
$this->bits = array();
|
||||
$this->bitcount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get what's been encoded so far.
|
||||
*/
|
||||
public function getvalue()
|
||||
{
|
||||
/* temporarily needed for compatibility with write_bit unit tests */
|
||||
if ($this->bitcount) {
|
||||
$this->flushbits();
|
||||
}
|
||||
|
||||
return $this->out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a plain PHP string, with no special encoding.
|
||||
*/
|
||||
public function write($s)
|
||||
{
|
||||
$this->out .= $s;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a boolean value.
|
||||
* (deprecated, use write_bits instead)
|
||||
*
|
||||
* @deprecated
|
||||
* @param $b
|
||||
* @return $this
|
||||
*/
|
||||
public function write_bit($b)
|
||||
{
|
||||
$b = (int) (bool) $b;
|
||||
$shift = $this->bitcount % 8;
|
||||
|
||||
if ($shift == 0) {
|
||||
$last = 0;
|
||||
} else {
|
||||
$last = array_pop($this->bits);
|
||||
}
|
||||
|
||||
$last |= ($b << $shift);
|
||||
array_push($this->bits, $last);
|
||||
$this->bitcount += 1;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write multiple bits as an octet
|
||||
*
|
||||
* @param $bits
|
||||
* @return $this
|
||||
*/
|
||||
public function write_bits($bits)
|
||||
{
|
||||
$value = 0;
|
||||
|
||||
foreach ($bits as $n => $bit) {
|
||||
$bit = $bit ? 1 : 0;
|
||||
$value |= ($bit << $n);
|
||||
}
|
||||
|
||||
$this->out .= chr($value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an integer as an unsigned 8-bit value
|
||||
*
|
||||
* @param $n
|
||||
* @return $this
|
||||
* @throws \PhpAmqpLib\Exception\AMQPInvalidArgumentException
|
||||
*/
|
||||
public function write_octet($n)
|
||||
{
|
||||
if ($n < 0 || $n > 255) {
|
||||
throw new AMQPInvalidArgumentException('Octet out of range: ' . $n);
|
||||
}
|
||||
|
||||
$this->out .= chr($n);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function write_signed_octet($n)
|
||||
{
|
||||
if (($n < -128) || ($n > 127)) {
|
||||
throw new AMQPInvalidArgumentException('Signed octet out of range: ' . $n);
|
||||
}
|
||||
|
||||
$this->out .= pack('c', $n);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an integer as an unsigned 16-bit value
|
||||
*
|
||||
* @param $n
|
||||
* @return $this
|
||||
* @throws \PhpAmqpLib\Exception\AMQPInvalidArgumentException
|
||||
*/
|
||||
public function write_short($n)
|
||||
{
|
||||
if ($n < 0 || $n > 65535) {
|
||||
throw new AMQPInvalidArgumentException('Short out of range: ' . $n);
|
||||
}
|
||||
|
||||
$this->out .= pack('n', $n);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function write_signed_short($n)
|
||||
{
|
||||
if (($n < -32768) || ($n > 32767)) {
|
||||
throw new AMQPInvalidArgumentException('Signed short out of range: ' . $n);
|
||||
}
|
||||
|
||||
$this->out .= $this->correctEndianness(pack('s', $n));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an integer as an unsigned 32-bit value
|
||||
*
|
||||
* @param $n
|
||||
* @return $this
|
||||
*/
|
||||
public function write_long($n)
|
||||
{
|
||||
if (($n < 0) || ($n > 4294967295)) {
|
||||
throw new AMQPInvalidArgumentException('Long out of range: ' . $n);
|
||||
}
|
||||
|
||||
//Numeric strings >PHP_INT_MAX on 32bit are casted to PHP_INT_MAX, damn PHP
|
||||
if (!$this->is64bits && is_string($n)) {
|
||||
$n = (float) $n;
|
||||
}
|
||||
$this->out .= pack('N', $n);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $n
|
||||
* @return $this
|
||||
*/
|
||||
private function write_signed_long($n)
|
||||
{
|
||||
if (($n < -2147483648) || ($n > 2147483647)) {
|
||||
throw new AMQPInvalidArgumentException('Signed long out of range: ' . $n);
|
||||
}
|
||||
|
||||
//on my 64bit debian this approach is slightly faster than splitIntoQuads()
|
||||
$this->out .= $this->correctEndianness(pack('l', $n));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an integer as an unsigned 64-bit value
|
||||
*
|
||||
* @param $n
|
||||
* @return $this
|
||||
*/
|
||||
public function write_longlong($n)
|
||||
{
|
||||
if ($n < 0) {
|
||||
throw new AMQPInvalidArgumentException('Longlong out of range: ' . $n);
|
||||
}
|
||||
|
||||
// if PHP_INT_MAX is big enough for that
|
||||
// direct $n<=PHP_INT_MAX check is unreliable on 64bit (values close to max) due to limited float precision
|
||||
if (bcadd($n, -PHP_INT_MAX, 0) <= 0) {
|
||||
// trick explained in http://www.php.net/manual/fr/function.pack.php#109328
|
||||
if ($this->is64bits) {
|
||||
list($hi, $lo) = $this->splitIntoQuads($n);
|
||||
} else {
|
||||
$hi = 0;
|
||||
$lo = $n;
|
||||
} //on 32bits hi quad is 0 a priori
|
||||
$this->out .= pack('NN', $hi, $lo);
|
||||
} else {
|
||||
try {
|
||||
$this->out .= self::packBigEndian($n, 8);
|
||||
} catch (AMQPOutOfBoundsException $ex) {
|
||||
throw new AMQPInvalidArgumentException('Longlong out of range: ' . $n, 0, $ex);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function write_signed_longlong($n)
|
||||
{
|
||||
if ((bcadd($n, PHP_INT_MAX, 0) >= -1) && (bcadd($n, -PHP_INT_MAX, 0) <= 0)) {
|
||||
if ($this->is64bits) {
|
||||
list($hi, $lo) = $this->splitIntoQuads($n);
|
||||
} else {
|
||||
$hi = $n < 0 ? -1 : 0;
|
||||
$lo = $n;
|
||||
} //0xffffffff for negatives
|
||||
$this->out .= pack('NN', $hi, $lo);
|
||||
} elseif ($this->is64bits) {
|
||||
throw new AMQPInvalidArgumentException('Signed longlong out of range: ' . $n);
|
||||
} else {
|
||||
if (bcadd($n, '-9223372036854775807', 0) > 0) {
|
||||
throw new AMQPInvalidArgumentException('Signed longlong out of range: ' . $n);
|
||||
}
|
||||
try {
|
||||
//will catch only negative overflow, as values >9223372036854775807 are valid for 8bytes range (unsigned)
|
||||
$this->out .= self::packBigEndian($n, 8);
|
||||
} catch (AMQPOutOfBoundsException $ex) {
|
||||
throw new AMQPInvalidArgumentException('Signed longlong out of range: ' . $n, 0, $ex);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $n
|
||||
* @return array
|
||||
*/
|
||||
private function splitIntoQuads($n)
|
||||
{
|
||||
$n = (int) $n;
|
||||
|
||||
return array($n >> 32, $n & 0x00000000ffffffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string up to 255 bytes long after encoding.
|
||||
* Assume UTF-8 encoding
|
||||
*
|
||||
* @param $s
|
||||
* @return $this
|
||||
* @throws \PhpAmqpLib\Exception\AMQPInvalidArgumentException
|
||||
*/
|
||||
public function write_shortstr($s)
|
||||
{
|
||||
$len = mb_strlen($s, 'ASCII');
|
||||
if ($len > 255) {
|
||||
throw new AMQPInvalidArgumentException('String too long');
|
||||
}
|
||||
|
||||
$this->write_octet($len);
|
||||
$this->out .= $s;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string up to 2**32 bytes long. Assume UTF-8 encoding
|
||||
*
|
||||
* @param $s
|
||||
* @return $this
|
||||
*/
|
||||
public function write_longstr($s)
|
||||
{
|
||||
$this->write_long(mb_strlen($s, 'ASCII'));
|
||||
$this->out .= $s;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supports the writing of Array types, so that you can implement
|
||||
* array methods, like Rabbitmq's HA parameters
|
||||
*
|
||||
* @param AMQPArray|array $a Instance of AMQPArray or PHP array WITHOUT format hints (unlike write_table())
|
||||
* @return self
|
||||
*/
|
||||
public function write_array($a)
|
||||
{
|
||||
if (!($a instanceof AMQPArray)) {
|
||||
$a = new AMQPArray($a);
|
||||
}
|
||||
$data = new AMQPWriter();
|
||||
|
||||
foreach ($a as $v) {
|
||||
$data->write_value($v[0], $v[1]);
|
||||
}
|
||||
|
||||
$data = $data->getvalue();
|
||||
$this->write_long(mb_strlen($data, 'ASCII'));
|
||||
$this->write($data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write unix time_t value as 64 bit timestamp
|
||||
*
|
||||
* @param $v
|
||||
* @return $this
|
||||
*/
|
||||
public function write_timestamp($v)
|
||||
{
|
||||
$this->write_longlong($v);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write PHP array, as table. Input array format: keys are strings,
|
||||
* values are (type,value) tuples.
|
||||
*
|
||||
* @param AMQPTable|array $d Instance of AMQPTable or PHP array WITH format hints (unlike write_array())
|
||||
* @return self
|
||||
* @throws \PhpAmqpLib\Exception\AMQPInvalidArgumentException
|
||||
*/
|
||||
public function write_table($d)
|
||||
{
|
||||
$typeIsSym = !($d instanceof AMQPTable); //purely for back-compat purposes
|
||||
|
||||
$table_data = new AMQPWriter();
|
||||
foreach ($d as $k => $va) {
|
||||
list($ftype, $v) = $va;
|
||||
$table_data->write_shortstr($k);
|
||||
$table_data->write_value($typeIsSym ? AMQPAbstractCollection::getDataTypeForSymbol($ftype) : $ftype, $v);
|
||||
}
|
||||
|
||||
$table_data = $table_data->getvalue();
|
||||
$this->write_long(mb_strlen($table_data, 'ASCII'));
|
||||
$this->write($table_data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* for compat with method mapping used by AMQPMessage
|
||||
*/
|
||||
public function write_table_object($d)
|
||||
{
|
||||
return $this->write_table($d);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type One of AMQPAbstractCollection::T_* constants
|
||||
* @param mixed $val
|
||||
*/
|
||||
private function write_value($type, $val)
|
||||
{
|
||||
//This will find appropriate symbol for given data type for currently selected protocol
|
||||
//Also will raise an exception on unknown type
|
||||
$this->write(AMQPAbstractCollection::getSymbolForDataType($type));
|
||||
|
||||
switch ($type) {
|
||||
case AMQPAbstractCollection::T_INT_SHORTSHORT:
|
||||
$this->write_signed_octet($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_SHORTSHORT_U:
|
||||
$this->write_octet($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_SHORT:
|
||||
$this->write_signed_short($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_SHORT_U:
|
||||
$this->write_short($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_LONG:
|
||||
$this->write_signed_long($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_LONG_U:
|
||||
$this->write_long($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_LONGLONG:
|
||||
$this->write_signed_longlong($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_INT_LONGLONG_U:
|
||||
$this->write_longlong($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_DECIMAL:
|
||||
$this->write_octet($val->e);
|
||||
$this->write_signed_long($val->n);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_TIMESTAMP:
|
||||
$this->write_timestamp($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_BOOL:
|
||||
$this->write_octet($val ? 1 : 0);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_STRING_SHORT:
|
||||
$this->write_shortstr($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_STRING_LONG:
|
||||
$this->write_longstr($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_ARRAY:
|
||||
$this->write_array($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_TABLE:
|
||||
$this->write_table($val);
|
||||
break;
|
||||
case AMQPAbstractCollection::T_VOID:
|
||||
break;
|
||||
default:
|
||||
throw new AMQPInvalidArgumentException(sprintf(
|
||||
'Unsupported type "%s"',
|
||||
$type
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
36
lib/PhpAmqpLib/Wire/AbstractClient.php
Normal file
36
lib/PhpAmqpLib/Wire/AbstractClient.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire;
|
||||
|
||||
|
||||
class AbstractClient
|
||||
{
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $is64bits;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isLittleEndian;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->is64bits = PHP_INT_SIZE == 8;
|
||||
|
||||
$tmp = unpack('S', "\x01\x00"); // to maintain 5.3 compatibility
|
||||
$this->isLittleEndian = $tmp[1] == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts byte-string between native and network byte order, in both directions
|
||||
*
|
||||
* @param string $byteStr
|
||||
* @return string
|
||||
*/
|
||||
protected function correctEndianness($byteStr)
|
||||
{
|
||||
return $this->isLittleEndian ? strrev($byteStr) : $byteStr;
|
||||
}
|
||||
}
|
||||
142
lib/PhpAmqpLib/Wire/Constants080.php
Normal file
142
lib/PhpAmqpLib/Wire/Constants080.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/* This file was autogenerated by spec/parser.php - Do not modify */
|
||||
|
||||
namespace PhpAmqpLib\Wire;
|
||||
|
||||
class Constants080
|
||||
{
|
||||
|
||||
public static $AMQP_PROTOCOL_HEADER = "AMQP\x01\x01\x08\x00";
|
||||
|
||||
public static $FRAME_TYPES = array(
|
||||
1 => 'FRAME-METHOD',
|
||||
2 => 'FRAME-HEADER',
|
||||
3 => 'FRAME-BODY',
|
||||
4 => 'FRAME-OOB-METHOD',
|
||||
5 => 'FRAME-OOB-HEADER',
|
||||
6 => 'FRAME-OOB-BODY',
|
||||
7 => 'FRAME-TRACE',
|
||||
8 => 'FRAME-HEARTBEAT',
|
||||
4096 => 'FRAME-MIN-SIZE',
|
||||
206 => 'FRAME-END',
|
||||
501 => 'FRAME-ERROR',
|
||||
);
|
||||
|
||||
public static $CONTENT_METHODS = array(
|
||||
0 => '60,40',
|
||||
1 => '60,50',
|
||||
2 => '60,60',
|
||||
3 => '60,71',
|
||||
4 => '70,50',
|
||||
5 => '70,70',
|
||||
6 => '80,40',
|
||||
7 => '80,50',
|
||||
8 => '80,60',
|
||||
9 => '110,10',
|
||||
10 => '120,40',
|
||||
11 => '120,41',
|
||||
);
|
||||
|
||||
public static $CLOSE_METHODS = array(
|
||||
0 => '10,60',
|
||||
1 => '20,40',
|
||||
);
|
||||
|
||||
public static $GLOBAL_METHOD_NAMES = array(
|
||||
'10,10' => 'Connection.start',
|
||||
'10,11' => 'Connection.start_ok',
|
||||
'10,20' => 'Connection.secure',
|
||||
'10,21' => 'Connection.secure_ok',
|
||||
'10,30' => 'Connection.tune',
|
||||
'10,31' => 'Connection.tune_ok',
|
||||
'10,40' => 'Connection.open',
|
||||
'10,41' => 'Connection.open_ok',
|
||||
'10,50' => 'Connection.redirect',
|
||||
'10,60' => 'Connection.close',
|
||||
'10,61' => 'Connection.close_ok',
|
||||
'20,10' => 'Channel.open',
|
||||
'20,11' => 'Channel.open_ok',
|
||||
'20,20' => 'Channel.flow',
|
||||
'20,21' => 'Channel.flow_ok',
|
||||
'20,30' => 'Channel.alert',
|
||||
'20,40' => 'Channel.close',
|
||||
'20,41' => 'Channel.close_ok',
|
||||
'30,10' => 'Access.request',
|
||||
'30,11' => 'Access.request_ok',
|
||||
'40,10' => 'Exchange.declare',
|
||||
'40,11' => 'Exchange.declare_ok',
|
||||
'40,20' => 'Exchange.delete',
|
||||
'40,21' => 'Exchange.delete_ok',
|
||||
'50,10' => 'Queue.declare',
|
||||
'50,11' => 'Queue.declare_ok',
|
||||
'50,20' => 'Queue.bind',
|
||||
'50,21' => 'Queue.bind_ok',
|
||||
'50,30' => 'Queue.purge',
|
||||
'50,31' => 'Queue.purge_ok',
|
||||
'50,40' => 'Queue.delete',
|
||||
'50,41' => 'Queue.delete_ok',
|
||||
'50,50' => 'Queue.unbind',
|
||||
'50,51' => 'Queue.unbind_ok',
|
||||
'60,10' => 'Basic.qos',
|
||||
'60,11' => 'Basic.qos_ok',
|
||||
'60,20' => 'Basic.consume',
|
||||
'60,21' => 'Basic.consume_ok',
|
||||
'60,30' => 'Basic.cancel',
|
||||
'60,31' => 'Basic.cancel_ok',
|
||||
'60,40' => 'Basic.publish',
|
||||
'60,50' => 'Basic.return',
|
||||
'60,60' => 'Basic.deliver',
|
||||
'60,70' => 'Basic.get',
|
||||
'60,71' => 'Basic.get_ok',
|
||||
'60,72' => 'Basic.get_empty',
|
||||
'60,80' => 'Basic.ack',
|
||||
'60,90' => 'Basic.reject',
|
||||
'60,100' => 'Basic.recover_async',
|
||||
'60,110' => 'Basic.recover',
|
||||
'60,111' => 'Basic.recover_ok',
|
||||
'70,10' => 'File.qos',
|
||||
'70,11' => 'File.qos_ok',
|
||||
'70,20' => 'File.consume',
|
||||
'70,21' => 'File.consume_ok',
|
||||
'70,30' => 'File.cancel',
|
||||
'70,31' => 'File.cancel_ok',
|
||||
'70,40' => 'File.open',
|
||||
'70,41' => 'File.open_ok',
|
||||
'70,50' => 'File.stage',
|
||||
'70,60' => 'File.publish',
|
||||
'70,70' => 'File.return',
|
||||
'70,80' => 'File.deliver',
|
||||
'70,90' => 'File.ack',
|
||||
'70,100' => 'File.reject',
|
||||
'80,10' => 'Stream.qos',
|
||||
'80,11' => 'Stream.qos_ok',
|
||||
'80,20' => 'Stream.consume',
|
||||
'80,21' => 'Stream.consume_ok',
|
||||
'80,30' => 'Stream.cancel',
|
||||
'80,31' => 'Stream.cancel_ok',
|
||||
'80,40' => 'Stream.publish',
|
||||
'80,50' => 'Stream.return',
|
||||
'80,60' => 'Stream.deliver',
|
||||
'90,10' => 'Tx.select',
|
||||
'90,11' => 'Tx.select_ok',
|
||||
'90,20' => 'Tx.commit',
|
||||
'90,21' => 'Tx.commit_ok',
|
||||
'90,30' => 'Tx.rollback',
|
||||
'90,31' => 'Tx.rollback_ok',
|
||||
'100,10' => 'Dtx.select',
|
||||
'100,11' => 'Dtx.select_ok',
|
||||
'100,20' => 'Dtx.start',
|
||||
'100,21' => 'Dtx.start_ok',
|
||||
'110,10' => 'Tunnel.request',
|
||||
'120,10' => 'Test.integer',
|
||||
'120,11' => 'Test.integer_ok',
|
||||
'120,20' => 'Test.string',
|
||||
'120,21' => 'Test.string_ok',
|
||||
'120,30' => 'Test.table',
|
||||
'120,31' => 'Test.table_ok',
|
||||
'120,40' => 'Test.content',
|
||||
'120,41' => 'Test.content_ok',
|
||||
);
|
||||
|
||||
}
|
||||
101
lib/PhpAmqpLib/Wire/Constants091.php
Normal file
101
lib/PhpAmqpLib/Wire/Constants091.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/* This file was autogenerated by spec/parser.php - Do not modify */
|
||||
|
||||
namespace PhpAmqpLib\Wire;
|
||||
|
||||
class Constants091
|
||||
{
|
||||
|
||||
public static $AMQP_PROTOCOL_HEADER = "AMQP\x00\x00\x09\x01";
|
||||
|
||||
public static $FRAME_TYPES = array(
|
||||
1 => 'FRAME-METHOD',
|
||||
2 => 'FRAME-HEADER',
|
||||
3 => 'FRAME-BODY',
|
||||
8 => 'FRAME-HEARTBEAT',
|
||||
4096 => 'FRAME-MIN-SIZE',
|
||||
206 => 'FRAME-END',
|
||||
501 => 'FRAME-ERROR',
|
||||
);
|
||||
|
||||
public static $CONTENT_METHODS = array(
|
||||
0 => '60,40',
|
||||
1 => '60,50',
|
||||
2 => '60,60',
|
||||
3 => '60,71',
|
||||
);
|
||||
|
||||
public static $CLOSE_METHODS = array(
|
||||
0 => '10,50',
|
||||
1 => '20,40',
|
||||
);
|
||||
|
||||
public static $GLOBAL_METHOD_NAMES = array(
|
||||
'10,10' => 'Connection.start',
|
||||
'10,11' => 'Connection.start_ok',
|
||||
'10,20' => 'Connection.secure',
|
||||
'10,21' => 'Connection.secure_ok',
|
||||
'10,30' => 'Connection.tune',
|
||||
'10,31' => 'Connection.tune_ok',
|
||||
'10,40' => 'Connection.open',
|
||||
'10,41' => 'Connection.open_ok',
|
||||
'10,50' => 'Connection.close',
|
||||
'10,51' => 'Connection.close_ok',
|
||||
'10,60' => 'Connection.blocked',
|
||||
'10,61' => 'Connection.unblocked',
|
||||
'20,10' => 'Channel.open',
|
||||
'20,11' => 'Channel.open_ok',
|
||||
'20,20' => 'Channel.flow',
|
||||
'20,21' => 'Channel.flow_ok',
|
||||
'20,40' => 'Channel.close',
|
||||
'20,41' => 'Channel.close_ok',
|
||||
'30,10' => 'Access.request',
|
||||
'30,11' => 'Access.request_ok',
|
||||
'40,10' => 'Exchange.declare',
|
||||
'40,11' => 'Exchange.declare_ok',
|
||||
'40,20' => 'Exchange.delete',
|
||||
'40,21' => 'Exchange.delete_ok',
|
||||
'40,30' => 'Exchange.bind',
|
||||
'40,31' => 'Exchange.bind_ok',
|
||||
'40,40' => 'Exchange.unbind',
|
||||
'40,51' => 'Exchange.unbind_ok',
|
||||
'50,10' => 'Queue.declare',
|
||||
'50,11' => 'Queue.declare_ok',
|
||||
'50,20' => 'Queue.bind',
|
||||
'50,21' => 'Queue.bind_ok',
|
||||
'50,30' => 'Queue.purge',
|
||||
'50,31' => 'Queue.purge_ok',
|
||||
'50,40' => 'Queue.delete',
|
||||
'50,41' => 'Queue.delete_ok',
|
||||
'50,50' => 'Queue.unbind',
|
||||
'50,51' => 'Queue.unbind_ok',
|
||||
'60,10' => 'Basic.qos',
|
||||
'60,11' => 'Basic.qos_ok',
|
||||
'60,20' => 'Basic.consume',
|
||||
'60,21' => 'Basic.consume_ok',
|
||||
'60,30' => 'Basic.cancel',
|
||||
'60,31' => 'Basic.cancel_ok',
|
||||
'60,40' => 'Basic.publish',
|
||||
'60,50' => 'Basic.return',
|
||||
'60,60' => 'Basic.deliver',
|
||||
'60,70' => 'Basic.get',
|
||||
'60,71' => 'Basic.get_ok',
|
||||
'60,72' => 'Basic.get_empty',
|
||||
'60,80' => 'Basic.ack',
|
||||
'60,90' => 'Basic.reject',
|
||||
'60,100' => 'Basic.recover_async',
|
||||
'60,110' => 'Basic.recover',
|
||||
'60,111' => 'Basic.recover_ok',
|
||||
'60,120' => 'Basic.nack',
|
||||
'90,10' => 'Tx.select',
|
||||
'90,11' => 'Tx.select_ok',
|
||||
'90,20' => 'Tx.commit',
|
||||
'90,21' => 'Tx.commit_ok',
|
||||
'90,30' => 'Tx.rollback',
|
||||
'90,31' => 'Tx.rollback_ok',
|
||||
'85,10' => 'Confirm.select',
|
||||
'85,11' => 'Confirm.select_ok',
|
||||
);
|
||||
|
||||
}
|
||||
209
lib/PhpAmqpLib/Wire/GenericContent.php
Normal file
209
lib/PhpAmqpLib/Wire/GenericContent.php
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire;
|
||||
|
||||
use PhpAmqpLib\Channel\AMQPChannel;
|
||||
|
||||
/**
|
||||
* Abstract base class for AMQP content. Subclasses should override
|
||||
* the PROPERTIES attribute.
|
||||
*/
|
||||
abstract class GenericContent
|
||||
{
|
||||
/** @var AMQPChannel[] */
|
||||
public $delivery_info = array();
|
||||
|
||||
/** @var array Final property definitions */
|
||||
protected $prop_types;
|
||||
|
||||
/** @var array Properties content */
|
||||
private $properties = array();
|
||||
|
||||
/** @var string Compiled properties */
|
||||
private $serialized_properties;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $PROPERTIES = array(
|
||||
'dummy' => 'shortstr'
|
||||
);
|
||||
|
||||
/**
|
||||
* @param $props
|
||||
* @param null $prop_types
|
||||
*/
|
||||
public function __construct($props, $prop_types = null)
|
||||
{
|
||||
if ($prop_types) {
|
||||
$this->prop_types = $prop_types;
|
||||
} else {
|
||||
$this->prop_types = self::$PROPERTIES;
|
||||
}
|
||||
|
||||
if ($props) {
|
||||
$this->properties = array_intersect_key($props, $this->prop_types);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a property exists in the 'properties' dictionary
|
||||
* or if present - in the 'delivery_info' dictionary.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function has($name)
|
||||
{
|
||||
return isset($this->properties[$name]) || isset($this->delivery_info[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for additional properties in the 'properties' dictionary,
|
||||
* and if present - the 'delivery_info' dictionary.
|
||||
*
|
||||
* @param string $name
|
||||
* @throws \OutOfBoundsException
|
||||
* @return mixed|AMQPChannel
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
if (isset($this->properties[$name])) {
|
||||
return $this->properties[$name];
|
||||
}
|
||||
|
||||
if (isset($this->delivery_info[$name])) {
|
||||
return $this->delivery_info[$name];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException(sprintf(
|
||||
'No "%s" property',
|
||||
$name
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the properties content
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_properties()
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a property value
|
||||
*
|
||||
* @param string $name The property name (one of the property definition)
|
||||
* @param mixed $value The property value
|
||||
* @throws \OutOfBoundsException
|
||||
*/
|
||||
public function set($name, $value)
|
||||
{
|
||||
if (!array_key_exists($name, $this->prop_types)) {
|
||||
throw new \OutOfBoundsException(sprintf(
|
||||
'No "%s" property',
|
||||
$name
|
||||
));
|
||||
}
|
||||
|
||||
$this->properties[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the raw bytes containing the property-flags and
|
||||
* property-list from a content-frame-header, parse and insert
|
||||
* into a dictionary stored in this object as an attribute named
|
||||
* 'properties'.
|
||||
*
|
||||
* @param AMQPReader $r
|
||||
* NOTE: do not mutate $reader
|
||||
*/
|
||||
public function load_properties($r)
|
||||
{
|
||||
// Read 16-bit shorts until we get one with a low bit set to zero
|
||||
$flags = array();
|
||||
while (true) {
|
||||
$flag_bits = $r->read_short();
|
||||
$flags[] = $flag_bits;
|
||||
if (($flag_bits & 1) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$shift = 0;
|
||||
$d = array();
|
||||
foreach ($this->prop_types as $key => $proptype) {
|
||||
if ($shift == 0) {
|
||||
if (!$flags) {
|
||||
break;
|
||||
}
|
||||
$flag_bits = array_shift($flags);
|
||||
$shift = 15;
|
||||
}
|
||||
if ($flag_bits & (1 << $shift)) {
|
||||
$d[$key] = $r->{'read_' . $proptype}();
|
||||
}
|
||||
|
||||
$shift -= 1;
|
||||
}
|
||||
$this->properties = $d;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the 'properties' attribute (a dictionary) into the
|
||||
* raw bytes making up a set of property flags and a property
|
||||
* list, suitable for putting into a content frame header.
|
||||
*
|
||||
* @return string
|
||||
* @todo Inject the AMQPWriter to make the method easier to test
|
||||
*/
|
||||
public function serialize_properties()
|
||||
{
|
||||
if (!empty($this->serialized_properties)) {
|
||||
return $this->serialized_properties;
|
||||
}
|
||||
|
||||
$shift = 15;
|
||||
$flag_bits = 0;
|
||||
$flags = array();
|
||||
$raw_bytes = new AMQPWriter();
|
||||
|
||||
foreach ($this->prop_types as $key => $prototype) {
|
||||
$val = isset($this->properties[$key]) ? $this->properties[$key] : null;
|
||||
|
||||
// Very important: PHP type eval is weak, use the === to test the
|
||||
// value content. Zero or false value should not be removed
|
||||
if ($val === null) {
|
||||
$shift -= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($shift === 0) {
|
||||
$flags[] = $flag_bits;
|
||||
$flag_bits = 0;
|
||||
$shift = 15;
|
||||
}
|
||||
|
||||
$flag_bits |= (1 << $shift);
|
||||
if ($prototype != 'bit') {
|
||||
$raw_bytes->{'write_' . $prototype}($val);
|
||||
}
|
||||
|
||||
$shift -= 1;
|
||||
}
|
||||
|
||||
$flags[] = $flag_bits;
|
||||
$result = new AMQPWriter();
|
||||
foreach ($flags as $flag_bits) {
|
||||
$result->write_short($flag_bits);
|
||||
}
|
||||
|
||||
$result->write($raw_bytes->getvalue());
|
||||
|
||||
$this->serialized_properties = $result->getvalue();
|
||||
|
||||
return $this->serialized_properties;
|
||||
}
|
||||
}
|
||||
44
lib/PhpAmqpLib/Wire/IO/AbstractIO.php
Normal file
44
lib/PhpAmqpLib/Wire/IO/AbstractIO.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire\IO;
|
||||
|
||||
abstract class AbstractIO
|
||||
{
|
||||
/**
|
||||
* @param $n
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function read($n);
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function write($data);
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function close();
|
||||
|
||||
/**
|
||||
* @param $sec
|
||||
* @param $usec
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function select($sec, $usec);
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function connect();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function reconnect();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function getSocket();
|
||||
}
|
||||
195
lib/PhpAmqpLib/Wire/IO/SocketIO.php
Normal file
195
lib/PhpAmqpLib/Wire/IO/SocketIO.php
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire\IO;
|
||||
|
||||
use PhpAmqpLib\Exception\AMQPIOException;
|
||||
use PhpAmqpLib\Exception\AMQPRuntimeException;
|
||||
|
||||
class SocketIO extends AbstractIO
|
||||
{
|
||||
/** @var string */
|
||||
protected $host;
|
||||
|
||||
/** @var int */
|
||||
protected $port;
|
||||
|
||||
/** @var int */
|
||||
protected $timeout;
|
||||
|
||||
/** @var resource */
|
||||
private $sock;
|
||||
|
||||
/** @var bool */
|
||||
private $keepalive;
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param int $timeout
|
||||
* @param bool $keepalive
|
||||
*/
|
||||
public function __construct($host, $port, $timeout, $keepalive = false)
|
||||
{
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->timeout = $timeout;
|
||||
$this->keepalive = $keepalive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the socket connection
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
$this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||
|
||||
socket_set_option($this->sock, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $this->timeout, 'usec' => 0));
|
||||
socket_set_option($this->sock, SOL_SOCKET, SO_SNDTIMEO, array('sec' => $this->timeout, 'usec' => 0));
|
||||
|
||||
if (!socket_connect($this->sock, $this->host, $this->port)) {
|
||||
$errno = socket_last_error($this->sock);
|
||||
$errstr = socket_strerror($errno);
|
||||
throw new AMQPIOException(sprintf(
|
||||
'Error Connecting to server (%s): %s',
|
||||
$errno,
|
||||
$errstr
|
||||
), $errno);
|
||||
}
|
||||
|
||||
socket_set_block($this->sock);
|
||||
socket_set_option($this->sock, SOL_TCP, TCP_NODELAY, 1);
|
||||
|
||||
if ($this->keepalive) {
|
||||
$this->enable_keepalive();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return resource
|
||||
*/
|
||||
public function getSocket()
|
||||
{
|
||||
return $this->sock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconnects the socket
|
||||
*/
|
||||
public function reconnect()
|
||||
{
|
||||
$this->close();
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $n
|
||||
* @return mixed|string
|
||||
* @throws \PhpAmqpLib\Exception\AMQPIOException
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
*/
|
||||
public function read($n)
|
||||
{
|
||||
$res = '';
|
||||
$read = 0;
|
||||
|
||||
$buf = socket_read($this->sock, $n);
|
||||
while ($read < $n && $buf !== '' && $buf !== false) {
|
||||
// Null sockets are invalid, throw exception
|
||||
if (is_null($this->sock)) {
|
||||
throw new AMQPRuntimeException(sprintf(
|
||||
'Socket was null! Last SocketError was: %s',
|
||||
socket_strerror(socket_last_error())
|
||||
));
|
||||
}
|
||||
|
||||
$read += mb_strlen($buf, 'ASCII');
|
||||
$res .= $buf;
|
||||
$buf = socket_read($this->sock, $n - $read);
|
||||
}
|
||||
|
||||
if (mb_strlen($res, 'ASCII') != $n) {
|
||||
throw new AMQPIOException(sprintf(
|
||||
'Error reading data. Received %s instead of expected %s bytes',
|
||||
mb_strlen($res, 'ASCII'),
|
||||
$n
|
||||
));
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return mixed|void
|
||||
* @throws \PhpAmqpLib\Exception\AMQPIOException
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
*/
|
||||
public function write($data)
|
||||
{
|
||||
$len = mb_strlen($data, 'ASCII');
|
||||
|
||||
while (true) {
|
||||
// Null sockets are invalid, throw exception
|
||||
if (is_null($this->sock)) {
|
||||
throw new AMQPRuntimeException(sprintf(
|
||||
'Socket was null! Last SocketError was: %s',
|
||||
socket_strerror(socket_last_error())
|
||||
));
|
||||
}
|
||||
|
||||
$sent = socket_write($this->sock, $data, $len);
|
||||
if ($sent === false) {
|
||||
throw new AMQPIOException(sprintf(
|
||||
'Error sending data. Last SocketError: %s',
|
||||
socket_strerror(socket_last_error())
|
||||
));
|
||||
}
|
||||
|
||||
// Check if the entire message has been sent
|
||||
if ($sent < $len) {
|
||||
// If not sent the entire message.
|
||||
// Get the part of the message that has not yet been sent as message
|
||||
$data = mb_substr($data, $sent, mb_strlen($data, 'ASCII') - $sent, 'ASCII');
|
||||
// Get the length of the not sent part
|
||||
$len -= $sent;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
if (is_resource($this->sock)) {
|
||||
socket_close($this->sock);
|
||||
}
|
||||
$this->sock = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sec
|
||||
* @param $usec
|
||||
* @return int|mixed
|
||||
*/
|
||||
public function select($sec, $usec)
|
||||
{
|
||||
$read = array($this->sock);
|
||||
$write = null;
|
||||
$except = null;
|
||||
|
||||
return socket_select($read, $write, $except, $sec, $usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \PhpAmqpLib\Exception\AMQPIOException
|
||||
*/
|
||||
protected function enable_keepalive()
|
||||
{
|
||||
if (!defined('SOL_SOCKET') || !defined('SO_KEEPALIVE')) {
|
||||
throw new AMQPIOException('Can not enable keepalive: SOL_SOCKET or SO_KEEPALIVE is not defined');
|
||||
}
|
||||
|
||||
socket_set_option($this->sock, SOL_SOCKET, SO_KEEPALIVE, 1);
|
||||
}
|
||||
}
|
||||
309
lib/PhpAmqpLib/Wire/IO/StreamIO.php
Normal file
309
lib/PhpAmqpLib/Wire/IO/StreamIO.php
Normal file
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
namespace PhpAmqpLib\Wire\IO;
|
||||
|
||||
use PhpAmqpLib\Exception\AMQPIOException;
|
||||
use PhpAmqpLib\Exception\AMQPRuntimeException;
|
||||
use PhpAmqpLib\Exception\AMQPTimeoutException;
|
||||
use PhpAmqpLib\Helper\MiscHelper;
|
||||
use PhpAmqpLib\Wire\AMQPWriter;
|
||||
|
||||
class StreamIO extends AbstractIO
|
||||
{
|
||||
/** @var string */
|
||||
protected $host;
|
||||
|
||||
/** @var int */
|
||||
protected $port;
|
||||
|
||||
/** @var int */
|
||||
protected $connection_timeout;
|
||||
|
||||
/** @var int */
|
||||
protected $read_write_timeout;
|
||||
|
||||
/** @var resource */
|
||||
protected $context;
|
||||
|
||||
/** @var bool */
|
||||
protected $keepalive;
|
||||
|
||||
/** @var int */
|
||||
protected $heartbeat;
|
||||
|
||||
/** @var float */
|
||||
protected $last_read;
|
||||
|
||||
/** @var float */
|
||||
protected $last_write;
|
||||
|
||||
/** @var resource */
|
||||
private $sock;
|
||||
|
||||
/** @var bool */
|
||||
private $canDispatchPcntlSignal;
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param int $connection_timeout
|
||||
* @param int $read_write_timeout
|
||||
* @param null $context
|
||||
* @param bool $keepalive
|
||||
* @param int $heartbeat
|
||||
*/
|
||||
public function __construct(
|
||||
$host,
|
||||
$port,
|
||||
$connection_timeout,
|
||||
$read_write_timeout,
|
||||
$context = null,
|
||||
$keepalive = false,
|
||||
$heartbeat = 0
|
||||
) {
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->connection_timeout = $connection_timeout;
|
||||
$this->read_write_timeout = $read_write_timeout;
|
||||
$this->context = $context;
|
||||
$this->keepalive = $keepalive;
|
||||
$this->heartbeat = $heartbeat;
|
||||
$this->canDispatchPcntlSignal = extension_loaded('pcntl') && function_exists('pcntl_signal_dispatch')
|
||||
&& (defined('AMQP_WITHOUT_SIGNALS') ? !AMQP_WITHOUT_SIGNALS : true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the stream connection
|
||||
*
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
$errstr = $errno = null;
|
||||
|
||||
if ($this->context) {
|
||||
$remote = sprintf('ssl://%s:%s', $this->host, $this->port);
|
||||
$this->sock = @stream_socket_client(
|
||||
$remote,
|
||||
$errno,
|
||||
$errstr,
|
||||
$this->connection_timeout,
|
||||
STREAM_CLIENT_CONNECT,
|
||||
$this->context
|
||||
);
|
||||
} else {
|
||||
$remote = sprintf('tcp://%s:%s', $this->host, $this->port);
|
||||
$this->sock = @stream_socket_client(
|
||||
$remote,
|
||||
$errno,
|
||||
$errstr,
|
||||
$this->connection_timeout,
|
||||
STREAM_CLIENT_CONNECT
|
||||
);
|
||||
}
|
||||
|
||||
if (!$this->sock) {
|
||||
throw new AMQPRuntimeException(sprintf(
|
||||
'Error Connecting to server (%s): %s',
|
||||
$errno,
|
||||
$errstr
|
||||
), $errno);
|
||||
}
|
||||
|
||||
list($sec, $uSec) = MiscHelper::splitSecondsMicroseconds($this->read_write_timeout);
|
||||
if (!stream_set_timeout($this->sock, $sec, $uSec)) {
|
||||
throw new AMQPIOException('Timeout could not be set');
|
||||
}
|
||||
|
||||
stream_set_blocking($this->sock, 1);
|
||||
|
||||
if ($this->keepalive) {
|
||||
$this->enable_keepalive();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconnects the socket
|
||||
*/
|
||||
public function reconnect()
|
||||
{
|
||||
$this->close();
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $n
|
||||
* @throws \PhpAmqpLib\Exception\AMQPIOException
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function read($n)
|
||||
{
|
||||
$res = '';
|
||||
$read = 0;
|
||||
|
||||
while ($read < $n && !feof($this->sock) && (false !== ($buf = fread($this->sock, $n - $read)))) {
|
||||
$this->check_heartbeat();
|
||||
|
||||
if ($buf === '') {
|
||||
if ($this->canDispatchPcntlSignal) {
|
||||
pcntl_signal_dispatch();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$read += mb_strlen($buf, 'ASCII');
|
||||
$res .= $buf;
|
||||
|
||||
$this->last_read = microtime(true);
|
||||
}
|
||||
|
||||
if (mb_strlen($res, 'ASCII') != $n) {
|
||||
throw new AMQPIOException(sprintf(
|
||||
'Error reading data. Received %s instead of expected %s bytes',
|
||||
mb_strlen($res, 'ASCII'),
|
||||
$n
|
||||
));
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return mixed|void
|
||||
* @throws \PhpAmqpLib\Exception\AMQPRuntimeException
|
||||
* @throws \PhpAmqpLib\Exception\AMQPTimeoutException
|
||||
*/
|
||||
public function write($data)
|
||||
{
|
||||
$len = mb_strlen($data, 'ASCII');
|
||||
while (true) {
|
||||
if (is_null($this->sock)) {
|
||||
throw new AMQPRuntimeException('Broken pipe or closed connection');
|
||||
}
|
||||
|
||||
if (false === ($written = @fwrite($this->sock, $data))) {
|
||||
throw new AMQPRuntimeException('Error sending data');
|
||||
}
|
||||
|
||||
if ($written === 0) {
|
||||
throw new AMQPRuntimeException('Broken pipe or closed connection');
|
||||
}
|
||||
|
||||
if ($this->timed_out()) {
|
||||
throw new AMQPTimeoutException('Error sending data. Socket connection timed out');
|
||||
}
|
||||
|
||||
$len = $len - $written;
|
||||
if ($len > 0) {
|
||||
$data = mb_substr($data, 0 - $len, 0 - $len, 'ASCII');
|
||||
} else {
|
||||
$this->last_write = microtime(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Heartbeat logic: check connection health here
|
||||
*/
|
||||
protected function check_heartbeat()
|
||||
{
|
||||
// ignore unless heartbeat interval is set
|
||||
if ($this->heartbeat !== 0 && $this->last_read && $this->last_write) {
|
||||
$t = microtime(true);
|
||||
$t_read = round($t - $this->last_read);
|
||||
$t_write = round($t - $this->last_write);
|
||||
|
||||
// server has gone away
|
||||
if (($this->heartbeat * 2) < $t_read) {
|
||||
$this->reconnect();
|
||||
}
|
||||
|
||||
// time for client to send a heartbeat
|
||||
if (($this->heartbeat / 2) < $t_write) {
|
||||
$this->write_heartbeat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a heartbeat message
|
||||
*/
|
||||
protected function write_heartbeat()
|
||||
{
|
||||
$pkt = new AMQPWriter();
|
||||
$pkt->write_octet(8);
|
||||
$pkt->write_short(0);
|
||||
$pkt->write_long(0);
|
||||
$pkt->write_octet(0xCE);
|
||||
$val = $pkt->getvalue();
|
||||
$this->write($pkt->getvalue());
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
if (is_resource($this->sock)) {
|
||||
fclose($this->sock);
|
||||
}
|
||||
$this->sock = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return resource
|
||||
*/
|
||||
public function get_socket()
|
||||
{
|
||||
return $this->sock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return resource
|
||||
*/
|
||||
public function getSocket()
|
||||
{
|
||||
return $this->get_socket();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sec
|
||||
* @param $usec
|
||||
* @return int|mixed
|
||||
*/
|
||||
public function select($sec, $usec)
|
||||
{
|
||||
$read = array($this->sock);
|
||||
$write = null;
|
||||
$except = null;
|
||||
|
||||
return stream_select($read, $write, $except, $sec, $usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
protected function timed_out()
|
||||
{
|
||||
// get status of socket to determine whether or not it has timed out
|
||||
$info = stream_get_meta_data($this->sock);
|
||||
|
||||
return $info['timed_out'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \PhpAmqpLib\Exception\AMQPIOException
|
||||
*/
|
||||
protected function enable_keepalive()
|
||||
{
|
||||
if (!function_exists('socket_import_stream')) {
|
||||
throw new AMQPIOException('Can not enable keepalive: function socket_import_stream does not exist');
|
||||
}
|
||||
|
||||
if (!defined('SOL_SOCKET') || !defined('SO_KEEPALIVE')) {
|
||||
throw new AMQPIOException('Can not enable keepalive: SOL_SOCKET or SO_KEEPALIVE is not defined');
|
||||
}
|
||||
|
||||
$socket = socket_import_stream($this->sock);
|
||||
socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1);
|
||||
}
|
||||
}
|
||||
64
lib/PhpAmqpLib/autoload.php
Normal file
64
lib/PhpAmqpLib/autoload.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
// @codingStandardsIgnoreFile
|
||||
// @codeCoverageIgnoreStart
|
||||
// this is an autogenerated file - do not edit
|
||||
spl_autoload_register(
|
||||
function($class) {
|
||||
static $classes = null;
|
||||
if ($classes === null) {
|
||||
$classes = array(
|
||||
'phpamqplib\\channel\\abstractchannel' => '/Channel/AbstractChannel.php',
|
||||
'phpamqplib\\channel\\amqpchannel' => '/Channel/AMQPChannel.php',
|
||||
'phpamqplib\\connection\\abstractconnection' => '/Connection/AbstractConnection.php',
|
||||
'phpamqplib\\connection\\amqpconnection' => '/Connection/AMQPConnection.php',
|
||||
'phpamqplib\\connection\\amqplazyconnection' => '/Connection/AMQPLazyConnection.php',
|
||||
'phpamqplib\\connection\\amqpsocketconnection' => '/Connection/AMQPSocketConnection.php',
|
||||
'phpamqplib\\connection\\amqpsslconnection' => '/Connection/AMQPSSLConnection.php',
|
||||
'phpamqplib\\connection\\amqpstreamconnection' => '/Connection/AMQPStreamConnection.php',
|
||||
'phpamqplib\\exception\\amqpbasiccancelexception' => '/Exception/AMQPBasicCancelException.php',
|
||||
'phpamqplib\\exception\\amqpchannelexception' => '/Exception/AMQPChannelException.php',
|
||||
'phpamqplib\\exception\\amqpconnectionexception' => '/Exception/AMQPConnectionException.php',
|
||||
'phpamqplib\\exception\\amqpexception' => '/Exception/AMQPException.php',
|
||||
'phpamqplib\\exception\\amqpexceptioninterface' => '/Exception/AMQPExceptionInterface.php',
|
||||
'phpamqplib\\exception\\amqpinvalidargumentexception' => '/Exception/AMQPInvalidArgumentException.php',
|
||||
'phpamqplib\\exception\\amqpioexception' => '/Exception/AMQPIOException.php',
|
||||
'phpamqplib\\exception\\amqplogicexception' => '/Exception/AMQPLogicException.php',
|
||||
'phpamqplib\\exception\\amqpoutofboundsexception' => '/Exception/AMQPOutOfBoundsException.php',
|
||||
'phpamqplib\\exception\\amqpoutofrangeexception' => '/Exception/AMQPOutOfRangeException.php',
|
||||
'phpamqplib\\exception\\amqpprotocolchannelexception' => '/Exception/AMQPProtocolChannelException.php',
|
||||
'phpamqplib\\exception\\amqpprotocolconnectionexception' => '/Exception/AMQPProtocolConnectionException.php',
|
||||
'phpamqplib\\exception\\amqpprotocolexception' => '/Exception/AMQPProtocolException.php',
|
||||
'phpamqplib\\exception\\amqpruntimeexception' => '/Exception/AMQPRuntimeException.php',
|
||||
'phpamqplib\\exception\\amqptimeoutexception' => '/Exception/AMQPTimeoutException.php',
|
||||
'phpamqplib\\helper\\mischelper' => '/Helper/MiscHelper.php',
|
||||
'phpamqplib\\helper\\protocol\\methodmap080' => '/Helper/Protocol/MethodMap080.php',
|
||||
'phpamqplib\\helper\\protocol\\methodmap091' => '/Helper/Protocol/MethodMap091.php',
|
||||
'phpamqplib\\helper\\protocol\\protocol080' => '/Helper/Protocol/Protocol080.php',
|
||||
'phpamqplib\\helper\\protocol\\protocol091' => '/Helper/Protocol/Protocol091.php',
|
||||
'phpamqplib\\helper\\protocol\\wait080' => '/Helper/Protocol/Wait080.php',
|
||||
'phpamqplib\\helper\\protocol\\wait091' => '/Helper/Protocol/Wait091.php',
|
||||
'phpamqplib\\message\\amqpmessage' => '/Message/AMQPMessage.php',
|
||||
'phpamqplib\\wire\\abstractclient' => '/Wire/AbstractClient.php',
|
||||
'phpamqplib\\wire\\amqpabstractcollection' => '/Wire/AMQPAbstractCollection.php',
|
||||
'phpamqplib\\wire\\amqparray' => '/Wire/AMQPArray.php',
|
||||
'phpamqplib\\wire\\amqpdecimal' => '/Wire/AMQPDecimal.php',
|
||||
'phpamqplib\\wire\\amqpreader' => '/Wire/AMQPReader.php',
|
||||
'phpamqplib\\wire\\amqptable' => '/Wire/AMQPTable.php',
|
||||
'phpamqplib\\wire\\amqpwriter' => '/Wire/AMQPWriter.php',
|
||||
'phpamqplib\\wire\\constants080' => '/Wire/Constants080.php',
|
||||
'phpamqplib\\wire\\constants091' => '/Wire/Constants091.php',
|
||||
'phpamqplib\\wire\\genericcontent' => '/Wire/GenericContent.php',
|
||||
'phpamqplib\\wire\\io\\abstractio' => '/Wire/IO/AbstractIO.php',
|
||||
'phpamqplib\\wire\\io\\socketio' => '/Wire/IO/SocketIO.php',
|
||||
'phpamqplib\\wire\\io\\streamio' => '/Wire/IO/StreamIO.php'
|
||||
);
|
||||
}
|
||||
$cn = strtolower($class);
|
||||
if (isset($classes[$cn])) {
|
||||
require __DIR__ . $classes[$cn];
|
||||
}
|
||||
},
|
||||
true,
|
||||
false
|
||||
);
|
||||
// @codeCoverageIgnoreEnd
|
||||
4
sql-schema/110.sql
Normal file
4
sql-schema/110.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
INSERT INTO config VALUES ('','alert.transports.canopsis.user','','','Canopsis User','alerting',0, 'transports', 0, 0, 0);
|
||||
INSERT INTO config VALUES ('','alert.transports.canopsis.passwd','','','Canopsis Password','alerting',0, 'transports', 0, 0, 0);
|
||||
INSERT INTO config VALUES ('','alert.transports.canopsis.host','','','Canopsis Hostname','alerting',0, 'transports', 0, 0, 0);
|
||||
INSERT INTO config VALUES ('','alert.transports.canopsis.vhost','','','Canopsis vHost','alerting',0, 'transports', 0, 0, 0);
|
||||
Reference in New Issue
Block a user