Пример #1
0
 /**
  * Callback  from the  Connection  object for  channel frames  and
  * messages.  Only channel class methods should be delivered here.
  * @param   $meth           A channel method for this channel
  * @return  boolean         True:  Add message to internal queue for regular delivery
  *                          False: Remove message from internal queue
  */
 function handleChannelMessage(wire\Method $meth)
 {
     switch ($meth->amqpClass) {
         case 'channel.flow':
             $this->flow = !$this->flow;
             if ($r = $meth->getMethodProto()->getResponses()) {
                 $meth = new wire\Method($r[0], $this->chanId);
                 $this->invoke($meth);
             }
             return false;
         case 'channel.close':
             $pl = $this->myConn->getProtocolLoader();
             if ($culprit = $pl('ClassFactory', 'GetMethod', array($meth->getField('class-id'), $meth->getField('method-id')))) {
                 $culprit = $culprit->getSpecName();
             } else {
                 $culprit = '(Unknown or unspecified)';
             }
             // Note: ignores the soft-error, hard-error distinction in the xml
             $errCode = $pl('ProtoConsts', 'Konstant', array($meth->getField('reply-code')));
             $eb = '';
             foreach ($meth->getFields() as $k => $v) {
                 $eb .= sprintf("(%s=%s) ", $k, $v);
             }
             $tmp = $meth->getMethodProto()->getResponses();
             $closeOk = new wire\Method($tmp[0], $this->chanId);
             $em = "[channel.close] reply-code={$errCode['name']} triggered by {$culprit}: {$eb}";
             try {
                 $this->myConn->invoke($closeOk);
                 $em .= " Channel closed OK";
                 $n = 3687;
             } catch (\Exception $e) {
                 $em .= " Additionally, channel closure ack send failed";
                 $n = 2435;
             }
             throw new \Exception($em, $n);
         case 'channel.close-ok':
         case 'channel.open-ok':
         case 'channel.flow-ok':
             return true;
         default:
             throw new \Exception("Received unexpected channel message: {$meth->amqpClass}", 8795);
     }
 }
Пример #2
0
 /**
  * Send the given method immediately, optionally wait for the response.
  * @arg  Method     $inMeth         The method to send
  * @arg  boolean    $noWait         Flag that prevents the default behaviour of immediately
  *                                  waiting for a response - used mainly during consume.  NOTE
  *                                  that this mechanism can also be triggered via. the use of
  *                                  an Amqp no-wait domain field set to true
  */
 function invoke(wire\Method $inMeth, $noWait = false)
 {
     if (!$this->write($inMeth->toBin($this->getProtocolLoader()))) {
         throw new \Exception("Send message failed (1)", 5623);
     }
     if (!$noWait && $inMeth->getMethodProto()->getSpecResponseMethods()) {
         if ($inMeth->getMethodProto()->hasNoWaitField()) {
             foreach ($inMeth->getMethodProto()->getFields() as $f) {
                 if ($f->getSpecDomainName() == 'no-wait' && $inMeth->getField($f->getSpecFieldName())) {
                     return;
                 }
             }
         }
         while (true) {
             if (!($buff = $this->read())) {
                 throw new \Exception(sprintf("(2) Send message failed for %s", $inMeth->amqpClass), 5624);
             }
             $meths = $this->readMessages($buff);
             foreach (array_keys($meths) as $k) {
                 $meth = $meths[$k];
                 unset($meths[$k]);
                 if ($inMeth->isResponse($meth)) {
                     if ($meths) {
                         $this->unDelivered = array_merge($this->unDelivered, $meths);
                     }
                     return $meth;
                 } else {
                     $this->unDelivered[] = $meth;
                 }
             }
         }
     }
 }