/**
  * Determine how to deliver the message. This depends on what's in the interface configuration, delivery section.
  * If a callback is supplied, that is executed.
  * @param <type> $msg
  * @param <type> $conf
  * @TODO: would be easy to generalise onerror into a list of these actions that are
  *       done in sequence. e.g. log an error and then requeue it.
  * @TODO: would be good to have a failure count on the error message. Not sure how to
  *       represent this generally.
  */
 static function deliver_message($msgframe, $conf)
 {
     if (!$conf || !isset($conf["delivery"])) {
         throw new Exception("deliver_message failed because it was not passed valid configuration with delivery section");
     }
     $del = $conf["delivery"];
     try {
         if (isset($del["requeue"])) {
             // delivery means stick it in another queue. This is expected to be an array with at least a queue name
             if (!is_array($del["requeue"])) {
                 throw new Exception("delivery of message failed because it specifies requeue, but it is not the expected array");
             }
             $newQueue = isset($del["requeue"]["queue"]) ? $del["requeue"]["queue"] : null;
             if (!$newQueue) {
                 throw new Exception("delivery of message failed because it specified requeue, but doesn't specify a queue");
             }
             $newConf = MessageQueue::get_queue_config($newQueue);
             if (isset($del["requeue"]["immediate"]) && $del["requeue"]["immediate"]) {
                 // Immediate execution - get the configuration for the queue, and recurse to deliver immediately.
                 MessageQueue::deliver_message($msgframe, $newConf);
             } else {
                 // Not immediate, so put this message on the specified queue, and it will hopefully get delivered at
                 // some later time.
                 MessageQueue::send($newConf, $msgframe);
             }
         } else {
             if (isset($del["callback"])) {
                 // delivery is via a callback
                 call_user_func_array($del["callback"], array($msgframe, $conf));
             } else {
                 if (is_object($msgframe->body) && $msgframe->body instanceof MessageExecutable) {
                     $msgframe->body->execute($msgframe, $conf);
                 } else {
                     throw new Exception("delivery of message failed because there is no specification of what to do with it");
                 }
             }
         }
     } catch (Exception $e) {
         // Look at the config to determine what to do with a failed message.
         $onerror = isset($del["onerror"]) ? $del["onerror"] : "drop";
         if (!is_array($onerror)) {
             $list = array($onerror);
         } else {
             $list = $onerror;
         }
         // There are two types of entry. Those with numeric keys have the action
         // as the value. Those with non-numeric keys have the key as the action,
         // and the value as an argument.
         foreach ($list as $key => $value) {
             if (is_numeric($key)) {
                 $action = $value;
                 $arg = null;
             } else {
                 $action = $key;
                 $arg = $value;
             }
             switch ($action) {
                 case "drop":
                     break;
                     // do nothing
                 // do nothing
                 case "requeue":
                     if (!$arg) {
                         $arg = $msgframe->queue;
                     }
                     // requeue on the same queue if not specified.
                     MessageQueue::send($arg, $msgframe->body, $msgframe->header);
                     break;
                 case "log":
                     SS_Log::log($e, null);
                     echo $e->getMessage();
                     break;
                 case "callback":
                     if (!$arg) {
                         throw new Exception("delivery of message failed with error callback indicated, but no callback function supplied");
                     }
                     call_user_func_array($arg, array($e, $msgframe));
                     break;
                 default:
                     throw new Exception("Invalid onerror action '{$action}'");
             }
         }
     }
 }
 /**
  * Given a message received by a remote system, unencode the message and deliver it.
  * @param  $queue
  * @param  $message
  * @return void
  */
 function processRawMessage($raw)
 {
     $cooked = $this->decode($raw);
     $queue = $cooked["queue"];
     $msgframe = $cooked["msgframe"];
     $conf = MessageQueue::get_queue_config($queue);
     MessageQueue::decode_message($msgframe, $conf);
     MessageQueue::deliver_message($msgframe, $conf);
 }