Changeset View
Changeset View
Standalone View
Standalone View
externals/JAXL/xep/xep_0206.php
- This file was added.
<?php | |||||
/** | |||||
* Jaxl (Jabber XMPP Library) | |||||
* | |||||
* Copyright (c) 2009-2012, Abhinav Singh <me@abhinavsingh.com>. | |||||
* All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* | |||||
* * Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* | |||||
* * Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in | |||||
* the documentation and/or other materials provided with the | |||||
* distribution. | |||||
* | |||||
* * Neither the name of Abhinav Singh nor the names of his | |||||
* contributors may be used to endorse or promote products derived | |||||
* from this software without specific prior written permission. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||||
* POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
*/ | |||||
require_once JAXL_CWD.'/xmpp/xmpp_xep.php'; | |||||
define('NS_HTTP_BIND', 'http://jabber.org/protocol/httpbind'); | |||||
define('NS_BOSH', 'urn:xmpp:xbosh'); | |||||
class XEP_0206 extends XMPPXep { | |||||
private $mch = null; | |||||
public $chs = array(); | |||||
private $recv_cb = null; | |||||
public $rid = null; | |||||
public $sid = null; | |||||
private $hold = 1; | |||||
private $wait = 30; | |||||
private $restarted = false; | |||||
public $headers = array( | |||||
'Accept-Encoding: gzip, deflate', | |||||
'Content-Type: text/xml; charset=utf-8' | |||||
); | |||||
// | |||||
// abstract method | |||||
// | |||||
public function init() { | |||||
$this->mch = curl_multi_init(); | |||||
return array( | |||||
); | |||||
} | |||||
// | |||||
// event callbacks | |||||
// | |||||
public function send($body) { | |||||
if(is_object($body)) { | |||||
$body = $body->to_string(); | |||||
} | |||||
else { | |||||
if(substr($body, 0, 15) == '<stream:stream ') { | |||||
$this->restarted = true; | |||||
$body = new JAXLXml('body', NS_HTTP_BIND, array( | |||||
'sid' => $this->sid, | |||||
'rid' => ++$this->rid, | |||||
'to' => @$this->jaxl->jid ? $this->jaxl->jid->domain : $this->jaxl->cfg['domain'], | |||||
'xmpp:restart' => 'true', | |||||
'xmlns:xmpp' => NS_BOSH | |||||
)); | |||||
$body = $body->to_string(); | |||||
} | |||||
else if(substr($body, 0, 16) == '</stream:stream>') { | |||||
$body = new JAXLXml('body', NS_HTTP_BIND, array( | |||||
'sid' => $this->sid, | |||||
'rid' => ++$this->rid, | |||||
'type' => 'terminate' | |||||
)); | |||||
$body = $body->to_string(); | |||||
} | |||||
else { | |||||
$body = $this->wrap($body); | |||||
} | |||||
} | |||||
_debug("posting to ".$this->jaxl->cfg['bosh_url']." body ".$body); | |||||
$this->chs[$this->rid] = curl_init($this->jaxl->cfg['bosh_url']); | |||||
curl_setopt($this->chs[$this->rid], CURLOPT_RETURNTRANSFER, true); | |||||
curl_setopt($this->chs[$this->rid], CURLOPT_ENCODING, 'gzip,deflate'); | |||||
curl_setopt($this->chs[$this->rid], CURLOPT_HTTPHEADER, $this->headers); | |||||
curl_setopt($this->chs[$this->rid], CURLOPT_FOLLOWLOCATION, true); | |||||
curl_setopt($this->chs[$this->rid], CURLOPT_VERBOSE, false); | |||||
curl_setopt($this->chs[$this->rid], CURLOPT_POST, 1); | |||||
curl_setopt($this->chs[$this->rid], CURLOPT_POSTFIELDS, $body); | |||||
curl_multi_add_handle($this->mch, $this->chs[$this->rid]); | |||||
} | |||||
public function recv() { | |||||
if($this->restarted) { | |||||
$this->restarted = false; | |||||
// fool xmpp_stream state machine with stream start packet | |||||
// and make transition to wait_for_stream_features state | |||||
if($this->recv_cb) call_user_func($this->recv_cb, $this->jaxl->get_start_stream(new XMPPJid("bosh.jaxl"))); | |||||
} | |||||
_debug("recving for $this->rid"); | |||||
do { | |||||
$ret = curl_multi_exec($this->mch, $running); | |||||
$changed = curl_multi_select($this->mch, 0.1); | |||||
if($changed == 0 && $running == 0) { | |||||
$ch = @$this->chs[$this->rid]; | |||||
if($ch) { | |||||
$data = curl_multi_getcontent($ch); | |||||
curl_multi_remove_handle($this->mch, $ch); | |||||
unset($this->chs[$this->rid]); | |||||
_debug("recvd for $this->rid ".$data); | |||||
list($body, $stanza) = $this->unwrap($data); | |||||
$body = new SimpleXMLElement($body); | |||||
$attrs = $body->attributes(); | |||||
if(@$attrs['type'] == 'terminate') { | |||||
// fool me again | |||||
if($this->recv_cb) call_user_func($this->recv_cb, $this->jaxl->get_end_stream()); | |||||
} | |||||
else { | |||||
if(!$this->sid) { | |||||
$this->sid = $attrs['sid']; | |||||
} | |||||
if($this->recv_cb) call_user_func($this->recv_cb, $stanza); | |||||
} | |||||
} | |||||
else { | |||||
_error("no ch found"); | |||||
exit; | |||||
} | |||||
} | |||||
} while($running); | |||||
} | |||||
public function set_callback($recv_cb) { | |||||
$this->recv_cb = $recv_cb; | |||||
} | |||||
public function wrap($stanza) { | |||||
return '<body sid="'.$this->sid.'" rid="'.++$this->rid.'" xmlns="'.NS_HTTP_BIND.'">'.$stanza.'</body>'; | |||||
} | |||||
public function unwrap($body) { | |||||
// a dirty way but it works efficiently | |||||
if(substr($body, -2, 2) == "/>") preg_match_all('/<body (.*?)\/>/smi', $body, $m); | |||||
else preg_match_all('/<body (.*?)>(.*)<\/body>/smi', $body, $m); | |||||
if(isset($m[1][0])) $envelop = "<body ".$m[1][0]."/>"; | |||||
else $envelop = "<body/>"; | |||||
if(isset($m[2][0])) $payload = $m[2][0]; | |||||
else $payload = ''; | |||||
return array($envelop, $payload); | |||||
} | |||||
public function session_start() { | |||||
$this->rid = @$this->jaxl->cfg['bosh_rid'] ? $this->jaxl->cfg['bosh_rid'] : rand(1000, 10000); | |||||
$this->hold = @$this->jaxl->cfg['bosh_hold'] ? $this->jaxl->cfg['bosh_hold'] : $this->hold; | |||||
$this->wait = @$this->jaxl->cfg['bosh_wait'] ? $this->jaxl->cfg['bosh_wait'] : $this->wait; | |||||
// fool xmpp_stream state machine with stream start packet | |||||
// and make transition to wait_for_stream_features state | |||||
if($this->recv_cb) | |||||
call_user_func($this->recv_cb, $this->jaxl->get_start_stream(new XMPPJid("bosh.jaxl"))); | |||||
$attrs = array( | |||||
'content' => 'text/xml; charset=utf-8', | |||||
'to' => @$this->jaxl->jid ? $this->jaxl->jid->domain : $this->jaxl->cfg['domain'], | |||||
'route' => 'xmpp:'.$this->jaxl->cfg['host'].':'.$this->jaxl->cfg['port'], | |||||
'secure' => 'true', | |||||
'xml:lang' => 'en', | |||||
'xmpp:version' => '1.0', | |||||
'xmlns:xmpp' => NS_BOSH, | |||||
'hold' => $this->hold, | |||||
'wait' => $this->wait, | |||||
'rid' => $this->rid, | |||||
'ver' => '1.10' | |||||
); | |||||
if(@$this->jaxl->cfg['jid']) $attrs['from'] = @$this->jaxl->cfg['jid']; | |||||
$body = new JAXLXml('body', NS_HTTP_BIND, $attrs); | |||||
$this->send($body); | |||||
} | |||||
public function ping() { | |||||
$body = new JAXLXml('body', NS_HTTP_BIND, array('sid' => $this->sid, 'rid' => ++$this->rid)); | |||||
$this->send($body); | |||||
} | |||||
public function session_end() { | |||||
$this->disconnect(); | |||||
} | |||||
public function disconnect() { | |||||
_debug("disconnecting"); | |||||
} | |||||
} | |||||
?> |