PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/videlalvaro/php-amqplib/PhpAmqpLib/Channel/AbstractChannel.php

https://gitlab.com/shinvdu/rabbitMQ-php-test
PHP | 252 lines | 189 code | 47 blank | 16 comment | 37 complexity | d1d93f367e8cb59ed203a59813f9b807 MD5 | raw file
  1. <?php
  2. namespace PhpAmqpLib\Channel;
  3. use PhpAmqpLib\Connection\AbstractConnection;
  4. use PhpAmqpLib\Exception\AMQPOutOfBoundsException;
  5. use PhpAmqpLib\Exception\AMQPRuntimeException;
  6. use PhpAmqpLib\Helper\MiscHelper;
  7. use PhpAmqpLib\Wire\AMQPReader;
  8. use PhpAmqpLib\Message\AMQPMessage;
  9. use PhpAmqpLib\Helper\Protocol\Protocol080;
  10. use PhpAmqpLib\Helper\Protocol\Protocol091;
  11. use PhpAmqpLib\Helper\Protocol\Wait080;
  12. use PhpAmqpLib\Helper\Protocol\Wait091;
  13. use PhpAmqpLib\Helper\Protocol\MethodMap080;
  14. use PhpAmqpLib\Helper\Protocol\MethodMap091;
  15. class AbstractChannel
  16. {
  17. public static $PROTOCOL_CONSTANTS_CLASS;
  18. protected $debug;
  19. /**
  20. *
  21. * @var AbstractConnection
  22. */
  23. protected $connection;
  24. protected $protocolVersion;
  25. protected $protocolWriter;
  26. protected $waitHelper;
  27. protected $methodMap;
  28. protected $channel_id;
  29. /**
  30. * @param \PhpAmqpLib\Connection\AbstractConnection $connection
  31. * @param $channel_id
  32. */
  33. public function __construct(AbstractConnection $connection, $channel_id)
  34. {
  35. $this->connection = $connection;
  36. $this->channel_id = $channel_id;
  37. $connection->channels[$channel_id] = $this;
  38. $this->frame_queue = array(); // Lower level queue for frames
  39. $this->method_queue = array(); // Higher level queue for methods
  40. $this->auto_decode = false;
  41. $this->debug = defined('AMQP_DEBUG') ? AMQP_DEBUG : false;
  42. $this->protocolVersion = defined('AMQP_PROTOCOL') ? AMQP_PROTOCOL : '0.9.1';
  43. switch ($this->protocolVersion) {
  44. case '0.9.1':
  45. self::$PROTOCOL_CONSTANTS_CLASS = 'PhpAmqpLib\Wire\Constants091';
  46. $c = self::$PROTOCOL_CONSTANTS_CLASS;
  47. $this->amqp_protocol_header = $c::$AMQP_PROTOCOL_HEADER;
  48. $this->protocolWriter = new Protocol091();
  49. $this->waitHelper = new Wait091();
  50. $this->methodMap = new MethodMap091();
  51. break;
  52. case '0.8':
  53. self::$PROTOCOL_CONSTANTS_CLASS = 'PhpAmqpLib\Wire\Constants080';
  54. $c = self::$PROTOCOL_CONSTANTS_CLASS;
  55. $this->amqp_protocol_header = $c::$AMQP_PROTOCOL_HEADER;
  56. $this->protocolWriter = new Protocol080();
  57. $this->waitHelper = new Wait080();
  58. $this->methodMap = new MethodMap080();
  59. break;
  60. default:
  61. throw new AMQPRuntimeException('Protocol: ' . $this->protocolVersion . ' not implemented.');
  62. }
  63. }
  64. public function getChannelId()
  65. {
  66. return $this->channel_id;
  67. }
  68. public function dispatch($method_sig, $args, $content)
  69. {
  70. if (!$this->methodMap->valid_method($method_sig)) {
  71. throw new AMQPRuntimeException("Unknown AMQP method $method_sig");
  72. }
  73. $amqp_method = $this->methodMap->get_method($method_sig);
  74. if (!method_exists($this, $amqp_method)) {
  75. throw new AMQPRuntimeException("Method: $amqp_method not implemented by class: " . get_class($this));
  76. }
  77. if ($content == null) {
  78. return call_user_func(array($this, $amqp_method), $args);
  79. }
  80. return call_user_func(array($this, $amqp_method), $args, $content);
  81. }
  82. public function next_frame($timeout = 0)
  83. {
  84. if ($this->debug) {
  85. MiscHelper::debug_msg("waiting for a new frame");
  86. }
  87. if (!empty($this->frame_queue)) {
  88. return array_shift($this->frame_queue);
  89. }
  90. return $this->connection->wait_channel($this->channel_id, $timeout);
  91. }
  92. protected function send_method_frame($method_sig, $args="")
  93. {
  94. $this->connection->send_channel_method_frame($this->channel_id, $method_sig, $args);
  95. }
  96. public function wait_content()
  97. {
  98. $frm = $this->next_frame();
  99. $frame_type = $frm[0];
  100. $payload = $frm[1];
  101. if ($frame_type != 2) {
  102. throw new AMQPRuntimeException("Expecting Content header");
  103. }
  104. $payload_reader = new AMQPReader(substr($payload,0,12));
  105. $class_id = $payload_reader->read_short();
  106. $weight = $payload_reader->read_short();
  107. $body_size = $payload_reader->read_longlong();
  108. $msg = new AMQPMessage();
  109. $msg->load_properties(substr($payload,12));
  110. $body_parts = array();
  111. $body_received = 0;
  112. while (bccomp($body_size,$body_received) == 1) {
  113. $frm = $this->next_frame();
  114. $frame_type = $frm[0];
  115. $payload = $frm[1];
  116. if ($frame_type != 3) {
  117. $PROTOCOL_CONSTANTS_CLASS = self::$PROTOCOL_CONSTANTS_CLASS;
  118. throw new AMQPRuntimeException("Expecting Content body, received frame type $frame_type ("
  119. .$PROTOCOL_CONSTANTS_CLASS::$FRAME_TYPES[$frame_type].")");
  120. }
  121. $body_parts[] = $payload;
  122. $body_received = bcadd($body_received, strlen($payload));
  123. }
  124. $msg->body = implode("",$body_parts);
  125. if ($this->auto_decode && isset($msg->content_encoding)) {
  126. try {
  127. $msg->body = $msg->body->decode($msg->content_encoding);
  128. } catch (\Exception $e) {
  129. if ($this->debug) {
  130. MiscHelper::debug_msg("Ignoring body decoding exception: " . $e->getMessage());
  131. }
  132. }
  133. }
  134. return $msg;
  135. }
  136. /**
  137. * Wait for some expected AMQP methods and dispatch to them.
  138. * Unexpected methods are queued up for later calls to this PHP
  139. * method.
  140. */
  141. public function wait($allowed_methods=null, $non_blocking = false, $timeout = 0)
  142. {
  143. $PROTOCOL_CONSTANTS_CLASS = self::$PROTOCOL_CONSTANTS_CLASS;
  144. if ($allowed_methods && $this->debug) {
  145. MiscHelper::debug_msg("waiting for " . implode(", ", $allowed_methods));
  146. } elseif ($this->debug) {
  147. MiscHelper::debug_msg("waiting for any method");
  148. }
  149. //Process deferred methods
  150. foreach ($this->method_queue as $qk=>$queued_method) {
  151. if ($this->debug) {
  152. MiscHelper::debug_msg("checking queue method " . $qk);
  153. }
  154. $method_sig = $queued_method[0];
  155. if ($allowed_methods==null || in_array($method_sig, $allowed_methods)) {
  156. unset($this->method_queue[$qk]);
  157. if ($this->debug) {
  158. MiscHelper::debug_msg("Executing queued method: $method_sig: " .
  159. $PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)]);
  160. }
  161. return $this->dispatch($queued_method[0],
  162. $queued_method[1],
  163. $queued_method[2]);
  164. }
  165. }
  166. // No deferred methods? wait for new ones
  167. while (true) {
  168. $frm = $this->next_frame($timeout);
  169. $frame_type = $frm[0];
  170. $payload = $frm[1];
  171. if ($frame_type != 1) {
  172. throw new AMQPRuntimeException("Expecting AMQP method, received frame type: $frame_type ("
  173. .$PROTOCOL_CONSTANTS_CLASS::$FRAME_TYPES[$frame_type].")");
  174. }
  175. if (strlen($payload) < 4) {
  176. throw new AMQPOutOfBoundsException("Method frame too short");
  177. }
  178. $method_sig_array = unpack("n2", substr($payload,0,4));
  179. $method_sig = "" . $method_sig_array[1] . "," . $method_sig_array[2];
  180. $args = new AMQPReader(substr($payload,4));
  181. if ($this->debug) {
  182. MiscHelper::debug_msg("> $method_sig: " . $PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)]);
  183. }
  184. if (in_array($method_sig, $PROTOCOL_CONSTANTS_CLASS::$CONTENT_METHODS)) {
  185. $content = $this->wait_content();
  186. } else {
  187. $content = null;
  188. }
  189. if ($allowed_methods == null ||
  190. in_array($method_sig,$allowed_methods) ||
  191. in_array($method_sig, $PROTOCOL_CONSTANTS_CLASS::$CLOSE_METHODS)
  192. ) {
  193. return $this->dispatch($method_sig, $args, $content);
  194. }
  195. // Wasn't what we were looking for? save it for later
  196. if ($this->debug) {
  197. MiscHelper::debug_msg("Queueing for later: $method_sig: " . $PROTOCOL_CONSTANTS_CLASS::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)]);
  198. }
  199. $this->method_queue[] = array($method_sig, $args, $content);
  200. if ($non_blocking) {
  201. break;
  202. };
  203. }
  204. }
  205. }