595 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			595 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copyright 2005-2006 The Apache Software Foundation
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Licensed under the Apache License, Version 2.0 (the "License");
							 | 
						||
| 
								 | 
							
								 * you may not use this file except in compliance with the License.
							 | 
						||
| 
								 | 
							
								 * You may obtain a copy of the License at
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * http://www.apache.org/licenses/LICENSE-2.0
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Unless required by applicable law or agreed to in writing, software
							 | 
						||
| 
								 | 
							
								 * distributed under the License is distributed on an "AS IS" BASIS,
							 | 
						||
| 
								 | 
							
								 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
							 | 
						||
| 
								 | 
							
								 * See the License for the specific language governing permissions and
							 | 
						||
| 
								 | 
							
								 * limitations under the License.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* vim: set expandtab tabstop=3 shiftwidth=3: */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								require_once 'Stomp/Frame.php';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * A Stomp Connection
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @package Stomp
							 | 
						||
| 
								 | 
							
								 * @author Hiram Chirino <hiram@hiramchirino.com>
							 | 
						||
| 
								 | 
							
								 * @author Dejan Bosanac <dejan@nighttale.net> 
							 | 
						||
| 
								 | 
							
								 * @author Michael Caplan <mcaplan@labnet.net>
							 | 
						||
| 
								 | 
							
								 * @version $Revision: 43 $
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								class Stomp
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Perform request synchronously
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @var boolean
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public $sync = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Default prefetch size
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @var int
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
									public $prefetchSize = 1;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
								     * Client id used for durable subscriptions
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @var string
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
									public $clientId = null;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    protected $_brokerUri = null;
							 | 
						||
| 
								 | 
							
								    protected $_socket = null;
							 | 
						||
| 
								 | 
							
								    protected $_hosts = array();
							 | 
						||
| 
								 | 
							
								    protected $_params = array();
							 | 
						||
| 
								 | 
							
								    protected $_subscriptions = array();
							 | 
						||
| 
								 | 
							
								    protected $_defaultPort = 61613;
							 | 
						||
| 
								 | 
							
								    protected $_currentHost = - 1;
							 | 
						||
| 
								 | 
							
								    protected $_attempts = 10;
							 | 
						||
| 
								 | 
							
								    protected $_username = '';
							 | 
						||
| 
								 | 
							
								    protected $_password = '';
							 | 
						||
| 
								 | 
							
								    protected $_sessionId;
							 | 
						||
| 
								 | 
							
								    protected $_read_timeout_seconds = 60;
							 | 
						||
| 
								 | 
							
								    protected $_read_timeout_milliseconds = 0;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Constructor
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param string $brokerUri Broker URL
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function __construct ($brokerUri)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->_brokerUri = $brokerUri;
							 | 
						||
| 
								 | 
							
								        $this->_init();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Initialize connection
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function _init ()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $pattern = "|^(([a-zA-Z]+)://)+\(*([a-zA-Z0-9\.:/i,-]+)\)*\??([a-zA-Z0-9=]*)$|i";
							 | 
						||
| 
								 | 
							
								        if (preg_match($pattern, $this->_brokerUri, $regs)) {
							 | 
						||
| 
								 | 
							
								            $scheme = $regs[2];
							 | 
						||
| 
								 | 
							
								            $hosts = $regs[3];
							 | 
						||
| 
								 | 
							
								            $params = $regs[4];
							 | 
						||
| 
								 | 
							
								            if ($scheme != "failover") {
							 | 
						||
| 
								 | 
							
								                $this->_processUrl($this->_brokerUri);
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                $urls = explode(",", $hosts);
							 | 
						||
| 
								 | 
							
								                foreach ($urls as $url) {
							 | 
						||
| 
								 | 
							
								                    $this->_processUrl($url);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            if ($params != null) {
							 | 
						||
| 
								 | 
							
								                parse_str($params, $this->_params);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            require_once 'Stomp/Exception.php';
							 | 
						||
| 
								 | 
							
								            throw new Stomp_Exception("Bad Broker URL {$this->_brokerUri}");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Process broker URL
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param string $url Broker URL
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function _processUrl ($url)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $parsed = parse_url($url);
							 | 
						||
| 
								 | 
							
								        if ($parsed) {
							 | 
						||
| 
								 | 
							
								            array_push($this->_hosts, array($parsed['host'] , $parsed['port'] , $parsed['scheme']));
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            require_once 'Stomp/Exception.php';
							 | 
						||
| 
								 | 
							
								            throw new Stomp_Exception("Bad Broker URL $url");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Make socket connection to the server
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function _makeConnection ()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (count($this->_hosts) == 0) {
							 | 
						||
| 
								 | 
							
								            require_once 'Stomp/Exception.php';
							 | 
						||
| 
								 | 
							
								            throw new Stomp_Exception("No broker defined");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        // force disconnect, if previous established connection exists
							 | 
						||
| 
								 | 
							
								        $this->disconnect();
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        $i = $this->_currentHost;
							 | 
						||
| 
								 | 
							
								        $att = 0;
							 | 
						||
| 
								 | 
							
								        $connected = false;
							 | 
						||
| 
								 | 
							
								        while (! $connected && $att ++ < $this->_attempts) {
							 | 
						||
| 
								 | 
							
								            if (isset($this->_params['randomize']) && $this->_params['randomize'] == 'true') {
							 | 
						||
| 
								 | 
							
								                $i = rand(0, count($this->_hosts) - 1);
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                $i = ($i + 1) % count($this->_hosts);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $broker = $this->_hosts[$i];
							 | 
						||
| 
								 | 
							
								            $host = $broker[0];
							 | 
						||
| 
								 | 
							
								            $port = $broker[1];
							 | 
						||
| 
								 | 
							
								            $scheme = $broker[2];
							 | 
						||
| 
								 | 
							
								            if ($port == null) {
							 | 
						||
| 
								 | 
							
								                $port = $this->_defaultPort;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            if ($this->_socket != null) {
							 | 
						||
| 
								 | 
							
								                fclose($this->_socket);
							 | 
						||
| 
								 | 
							
								                $this->_socket = null;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $this->_socket = @fsockopen($scheme . '://' . $host, $port);
							 | 
						||
| 
								 | 
							
								            if (!is_resource($this->_socket) && $att >= $this->_attempts && !array_key_exists($i + 1, $this->_hosts)) {
							 | 
						||
| 
								 | 
							
								                require_once 'Stomp/Exception.php';
							 | 
						||
| 
								 | 
							
								                throw new Stomp_Exception("Could not connect to $host:$port ($att/{$this->_attempts})");
							 | 
						||
| 
								 | 
							
								            } else if (is_resource($this->_socket)) {
							 | 
						||
| 
								 | 
							
								                $connected = true;
							 | 
						||
| 
								 | 
							
								                $this->_currentHost = $i;
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (! $connected) {
							 | 
						||
| 
								 | 
							
								            require_once 'Stomp/Exception.php';
							 | 
						||
| 
								 | 
							
								            throw new Stomp_Exception("Could not connect to a broker");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Connect to server
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param string $username
							 | 
						||
| 
								 | 
							
								     * @param string $password
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function connect ($username = '', $password = '')
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->_makeConnection();
							 | 
						||
| 
								 | 
							
								        if ($username != '') {
							 | 
						||
| 
								 | 
							
								            $this->_username = $username;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if ($password != '') {
							 | 
						||
| 
								 | 
							
								            $this->_password = $password;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
										$headers = array('login' => $this->_username , 'passcode' => $this->_password);
							 | 
						||
| 
								 | 
							
										if ($this->clientId != null) {
							 | 
						||
| 
								 | 
							
											$headers["client-id"] = $this->clientId;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										$frame = new Stomp_Frame("CONNECT", $headers);
							 | 
						||
| 
								 | 
							
								        $this->_writeFrame($frame);
							 | 
						||
| 
								 | 
							
								        $frame = $this->readFrame();
							 | 
						||
| 
								 | 
							
								        if ($frame instanceof Stomp_Frame && $frame->command == 'CONNECTED') {
							 | 
						||
| 
								 | 
							
								            $this->_sessionId = $frame->headers["session"];
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            require_once 'Stomp/Exception.php';
							 | 
						||
| 
								 | 
							
								            if ($frame instanceof Stomp_Frame) {
							 | 
						||
| 
								 | 
							
								                throw new Stomp_Exception("Unexpected command: {$frame->command}", 0, $frame->body);
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                throw new Stomp_Exception("Connection not acknowledged");
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Check if client session has ben established
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function isConnected ()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return !empty($this->_sessionId) && is_resource($this->_socket);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Current stomp session ID
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @return string
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function getSessionId()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return $this->_sessionId;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Send a message to a destination in the messaging system 
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param string $destination Destination queue
							 | 
						||
| 
								 | 
							
								     * @param string|Stomp_Frame $msg Message
							 | 
						||
| 
								 | 
							
								     * @param array $properties
							 | 
						||
| 
								 | 
							
								     * @param boolean $sync Perform request synchronously
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function send ($destination, $msg, $properties = null, $sync = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if ($msg instanceof Stomp_Frame) {
							 | 
						||
| 
								 | 
							
								            $msg->headers['destination'] = $destination;
							 | 
						||
| 
								 | 
							
								            $msg->headers = array_merge($msg->headers, $properties);
							 | 
						||
| 
								 | 
							
								            $frame = $msg;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            $headers = $properties;
							 | 
						||
| 
								 | 
							
								            $headers['destination'] = $destination;
							 | 
						||
| 
								 | 
							
								            $frame = new Stomp_Frame('SEND', $headers, $msg);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $this->_prepareReceipt($frame, $sync);
							 | 
						||
| 
								 | 
							
								        $this->_writeFrame($frame);
							 | 
						||
| 
								 | 
							
								        return $this->_waitForReceipt($frame, $sync);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Prepair frame receipt
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param Stomp_Frame $frame
							 | 
						||
| 
								 | 
							
								     * @param boolean $sync
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function _prepareReceipt (Stomp_Frame $frame, $sync)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $receive = $this->sync;
							 | 
						||
| 
								 | 
							
								        if ($sync !== null) {
							 | 
						||
| 
								 | 
							
								            $receive = $sync;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if ($receive == true) {
							 | 
						||
| 
								 | 
							
								            $frame->headers['receipt'] = md5(microtime());
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Wait for receipt
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param Stomp_Frame $frame
							 | 
						||
| 
								 | 
							
								     * @param boolean $sync
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function _waitForReceipt (Stomp_Frame $frame, $sync)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $receive = $this->sync;
							 | 
						||
| 
								 | 
							
								        if ($sync !== null) {
							 | 
						||
| 
								 | 
							
								            $receive = $sync;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if ($receive == true) {
							 | 
						||
| 
								 | 
							
								            $id = (isset($frame->headers['receipt'])) ? $frame->headers['receipt'] : null;
							 | 
						||
| 
								 | 
							
								            if ($id == null) {
							 | 
						||
| 
								 | 
							
								                return true;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $frame = $this->readFrame();
							 | 
						||
| 
								 | 
							
								            if ($frame instanceof Stomp_Frame && $frame->command == 'RECEIPT') {
							 | 
						||
| 
								 | 
							
								                if ($frame->headers['receipt-id'] == $id) {
							 | 
						||
| 
								 | 
							
								                    return true;
							 | 
						||
| 
								 | 
							
								                } else {
							 | 
						||
| 
								 | 
							
								                    require_once 'Stomp/Exception.php';
							 | 
						||
| 
								 | 
							
								                    throw new Stomp_Exception("Unexpected receipt id {$frame->headers['receipt-id']}", 0, $frame->body);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                require_once 'Stomp/Exception.php';
							 | 
						||
| 
								 | 
							
								                if ($frame instanceof Stomp_Frame) {
							 | 
						||
| 
								 | 
							
								                    throw new Stomp_Exception("Unexpected command {$frame->command}", 0, $frame->body);
							 | 
						||
| 
								 | 
							
								                } else {
							 | 
						||
| 
								 | 
							
								                    throw new Stomp_Exception("Receipt not received");
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Register to listen to a given destination
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param string $destination Destination queue
							 | 
						||
| 
								 | 
							
								     * @param array $properties
							 | 
						||
| 
								 | 
							
								     * @param boolean $sync Perform request synchronously
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function subscribe ($destination, $properties = null, $sync = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $headers = array('ack' => 'client');
							 | 
						||
| 
								 | 
							
										$headers['activemq.prefetchSize'] = $this->prefetchSize;
							 | 
						||
| 
								 | 
							
										if ($this->clientId != null) {
							 | 
						||
| 
								 | 
							
											$headers["activemq.subcriptionName"] = $this->clientId;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								        if (isset($properties)) {
							 | 
						||
| 
								 | 
							
								            foreach ($properties as $name => $value) {
							 | 
						||
| 
								 | 
							
								                $headers[$name] = $value;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $headers['destination'] = $destination;
							 | 
						||
| 
								 | 
							
								        $frame = new Stomp_Frame('SUBSCRIBE', $headers);
							 | 
						||
| 
								 | 
							
								        $this->_prepareReceipt($frame, $sync);
							 | 
						||
| 
								 | 
							
								        $this->_writeFrame($frame);
							 | 
						||
| 
								 | 
							
								        if ($this->_waitForReceipt($frame, $sync) == true) {
							 | 
						||
| 
								 | 
							
								            $this->_subscriptions[$destination] = $properties;
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            return false;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Remove an existing subscription
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param string $destination
							 | 
						||
| 
								 | 
							
								     * @param array $properties
							 | 
						||
| 
								 | 
							
								     * @param boolean $sync Perform request synchronously
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function unsubscribe ($destination, $properties = null, $sync = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $headers = array();
							 | 
						||
| 
								 | 
							
								        if (isset($properties)) {
							 | 
						||
| 
								 | 
							
								            foreach ($properties as $name => $value) {
							 | 
						||
| 
								 | 
							
								                $headers[$name] = $value;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $headers['destination'] = $destination;
							 | 
						||
| 
								 | 
							
								        $frame = new Stomp_Frame('UNSUBSCRIBE', $headers);
							 | 
						||
| 
								 | 
							
								        $this->_prepareReceipt($frame, $sync);
							 | 
						||
| 
								 | 
							
								        $this->_writeFrame($frame);
							 | 
						||
| 
								 | 
							
								        if ($this->_waitForReceipt($frame, $sync) == true) {
							 | 
						||
| 
								 | 
							
								            unset($this->_subscriptions[$destination]);
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            return false;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Start a transaction
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param string $transactionId
							 | 
						||
| 
								 | 
							
								     * @param boolean $sync Perform request synchronously
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function begin ($transactionId = null, $sync = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $headers = array();
							 | 
						||
| 
								 | 
							
								        if (isset($transactionId)) {
							 | 
						||
| 
								 | 
							
								            $headers['transaction'] = $transactionId;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $frame = new Stomp_Frame('BEGIN', $headers);
							 | 
						||
| 
								 | 
							
								        $this->_prepareReceipt($frame, $sync);
							 | 
						||
| 
								 | 
							
								        $this->_writeFrame($frame);
							 | 
						||
| 
								 | 
							
								        return $this->_waitForReceipt($frame, $sync);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Commit a transaction in progress
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param string $transactionId
							 | 
						||
| 
								 | 
							
								     * @param boolean $sync Perform request synchronously
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function commit ($transactionId = null, $sync = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $headers = array();
							 | 
						||
| 
								 | 
							
								        if (isset($transactionId)) {
							 | 
						||
| 
								 | 
							
								            $headers['transaction'] = $transactionId;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $frame = new Stomp_Frame('COMMIT', $headers);
							 | 
						||
| 
								 | 
							
								        $this->_prepareReceipt($frame, $sync);
							 | 
						||
| 
								 | 
							
								        $this->_writeFrame($frame);
							 | 
						||
| 
								 | 
							
								        return $this->_waitForReceipt($frame, $sync);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Roll back a transaction in progress
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param string $transactionId
							 | 
						||
| 
								 | 
							
								     * @param boolean $sync Perform request synchronously
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function abort ($transactionId = null, $sync = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $headers = array();
							 | 
						||
| 
								 | 
							
								        if (isset($transactionId)) {
							 | 
						||
| 
								 | 
							
								            $headers['transaction'] = $transactionId;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $frame = new Stomp_Frame('ABORT', $headers);
							 | 
						||
| 
								 | 
							
								        $this->_prepareReceipt($frame, $sync);
							 | 
						||
| 
								 | 
							
								        $this->_writeFrame($frame);
							 | 
						||
| 
								 | 
							
								        return $this->_waitForReceipt($frame, $sync);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Acknowledge consumption of a message from a subscription
							 | 
						||
| 
								 | 
							
									 * Note: This operation is always asynchronous
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param string|Stomp_Frame $messageMessage ID
							 | 
						||
| 
								 | 
							
								     * @param string $transactionId
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     * @throws Stomp_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function ack ($message, $transactionId = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if ($message instanceof Stomp_Frame) {
							 | 
						||
| 
								 | 
							
								            $frame = new Stomp_Frame('ACK', $message->headers);
							 | 
						||
| 
								 | 
							
								            $this->_writeFrame($frame);
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            $headers = array();
							 | 
						||
| 
								 | 
							
								            if (isset($transactionId)) {
							 | 
						||
| 
								 | 
							
								                $headers['transaction'] = $transactionId;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $headers['message-id'] = $message;
							 | 
						||
| 
								 | 
							
								            $frame = new Stomp_Frame('ACK', $headers);
							 | 
						||
| 
								 | 
							
								            $this->_writeFrame($frame);
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Graceful disconnect from the server
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function disconnect ()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
										$header = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ($this->clientId != null) {
							 | 
						||
| 
								 | 
							
											$headers["client-id"] = $this->clientId;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (is_resource($this->_socket)) {
							 | 
						||
| 
								 | 
							
								            $this->_writeFrame(new Stomp_Frame('DISCONNECT', $headers));
							 | 
						||
| 
								 | 
							
								            fclose($this->_socket);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $this->_socket = null;
							 | 
						||
| 
								 | 
							
								        $this->_sessionId = null;
							 | 
						||
| 
								 | 
							
								        $this->_currentHost = -1;
							 | 
						||
| 
								 | 
							
								        $this->_subscriptions = array();
							 | 
						||
| 
								 | 
							
								        $this->_username = '';
							 | 
						||
| 
								 | 
							
								        $this->_password = '';
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Write frame to server
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param Stomp_Frame $stompFrame
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function _writeFrame (Stomp_Frame $stompFrame)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (!is_resource($this->_socket)) {
							 | 
						||
| 
								 | 
							
								            require_once 'Stomp/Exception.php';
							 | 
						||
| 
								 | 
							
								            throw new Stomp_Exception('Socket connection hasn\'t been established');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $data = $stompFrame->__toString();
							 | 
						||
| 
								 | 
							
								        $r = fwrite($this->_socket, $data, strlen($data));
							 | 
						||
| 
								 | 
							
								        if ($r === false || $r == 0) {
							 | 
						||
| 
								 | 
							
								            $this->_reconnect();
							 | 
						||
| 
								 | 
							
								            $this->_writeFrame($stompFrame);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Set timeout to wait for content to read
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param int $seconds_to_wait  Seconds to wait for a frame
							 | 
						||
| 
								 | 
							
								     * @param int $milliseconds Milliseconds to wait for a frame
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function setReadTimeout($seconds, $milliseconds = 0) 
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->_read_timeout_seconds = $seconds;
							 | 
						||
| 
								 | 
							
								        $this->_read_timeout_milliseconds = $milliseconds;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Read responce frame from server
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @return Stomp_Frame|Stomp_Message_Map|boolean False when no frame to read
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function readFrame ()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (!$this->hasFrameToRead()) {
							 | 
						||
| 
								 | 
							
								            return false;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        $rb = 1024;
							 | 
						||
| 
								 | 
							
								        $data = '';
							 | 
						||
| 
								 | 
							
								        do {
							 | 
						||
| 
								 | 
							
								            $read = fgets($this->_socket, $rb);
							 | 
						||
| 
								 | 
							
								            if ($read === false) {
							 | 
						||
| 
								 | 
							
								                $this->_reconnect();
							 | 
						||
| 
								 | 
							
								                return $this->readFrame();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $data .= $read;
							 | 
						||
| 
								 | 
							
								            $len = strlen($data);
							 | 
						||
| 
								 | 
							
								        } while (($len < 2 || ! ($data[$len - 2] == "\x00" && $data[$len - 1] == "\n")));
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        list ($header, $body) = explode("\n\n", $data, 2);
							 | 
						||
| 
								 | 
							
								        $header = explode("\n", $header);
							 | 
						||
| 
								 | 
							
								        $headers = array();
							 | 
						||
| 
								 | 
							
								        $command = null;
							 | 
						||
| 
								 | 
							
								        foreach ($header as $v) {
							 | 
						||
| 
								 | 
							
								            if (isset($command)) {
							 | 
						||
| 
								 | 
							
								                list ($name, $value) = explode(':', $v, 2);
							 | 
						||
| 
								 | 
							
								                $headers[$name] = $value;
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                $command = $v;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $frame = new Stomp_Frame($command, $headers, trim($body));
							 | 
						||
| 
								 | 
							
								        if (isset($frame->headers['amq-msg-type']) && $frame->headers['amq-msg-type'] == 'MapMessage') {
							 | 
						||
| 
								 | 
							
								            require_once 'Stomp/Message/Map.php';
							 | 
						||
| 
								 | 
							
								            return new Stomp_Message_Map($frame);
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            return $frame;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Check if there is a frame to read
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @return boolean
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function hasFrameToRead()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $read = array($this->_socket);
							 | 
						||
| 
								 | 
							
								        $write = null;
							 | 
						||
| 
								 | 
							
								        $except = null;
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        $has_frame_to_read = stream_select($read, $write, $except, $this->_read_timeout_seconds, $this->_read_timeout_milliseconds);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if ($has_frame_to_read === false) {
							 | 
						||
| 
								 | 
							
								            throw new Stomp_Exception('Check failed to determin if the socket is readable');
							 | 
						||
| 
								 | 
							
								        } else if ($has_frame_to_read > 0) {
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            return false; 
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Reconnects and renews subscriptions (if there were any)
							 | 
						||
| 
								 | 
							
								     * Call this method when you detect connection problems     
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function _reconnect ()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $subscriptions = $this->_subscriptions;
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        $this->connect($this->_username, $this->_password);
							 | 
						||
| 
								 | 
							
								        foreach ($subscriptions as $dest => $properties) {
							 | 
						||
| 
								 | 
							
								            $this->subscribe($dest, $properties);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Graceful object desruction
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function __destruct()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->disconnect();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								?>
							 |