/** * 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); } }
/** * 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; } } } } }