From 582b0a07705f965b04e829449a703eba20c2a8cb Mon Sep 17 00:00:00 2001 From: Christian Weiske Date: Wed, 24 Feb 2010 06:01:22 +0800 Subject: [PATCH 1/3] Fix that damn cpu-hogging bug --- XMPPHP/XMLStream.php | 55 ++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/XMPPHP/XMLStream.php b/XMPPHP/XMLStream.php index d33411e..d9e99cc 100644 --- a/XMPPHP/XMLStream.php +++ b/XMPPHP/XMLStream.php @@ -370,13 +370,18 @@ class XMPPHP_XMLStream { /** * Core reading tool - * 0 -> only read if data is immediately ready - * NULL -> wait forever and ever - * integer -> process for this amount of time + * + * @param mixed $maximum Limit when to return + * - 0: only read if data is immediately ready + * - NULL: wait forever and ever + * - integer: process for this amount of milliseconds + * @param boolean $return_when_received Immediately return when data have been + * received + * + * @return boolean True when all goes well, false when something fails */ - - private function __process($maximum=5) { - + private function __process($maximum = 5, $return_when_received = false) + { $remaining = $maximum; do { @@ -418,6 +423,9 @@ class XMPPHP_XMLStream { } $this->log->log("RECV: $buff", XMPPHP_Log::LEVEL_VERBOSE); xml_parse($this->parser, $buff, false); + if ($return_when_received) { + return true; + } } else { # $updated == 0 means no changes during timeout. } @@ -440,8 +448,11 @@ class XMPPHP_XMLStream { /** * Process until a timeout occurs * - * @param integer $timeout + * @param integer $timeout Time in seconds + * * @return string + * + * @see __process() */ public function processTime($timeout=NULL) { if (is_null($timeout)) { @@ -454,23 +465,36 @@ class XMPPHP_XMLStream { /** * Process until a specified event or a timeout occurs * - * @param string|array $event - * @param integer $timeout - * @return string + * @param string|array $event Event name or array of event names + * @param integer $timeout Timeout in seconds + * + * @return array Payload */ - public function processUntil($event, $timeout=-1) { + public function processUntil($event, $timeout = -1) + { $start = time(); - if(!is_array($event)) $event = array($event); + if (!is_array($event)) { + $event = array($event); + } + $this->until[] = $event; end($this->until); $event_key = key($this->until); reset($this->until); + $this->until_count[$event_key] = 0; $updated = ''; - while(!$this->disconnected and $this->until_count[$event_key] < 1 and (time() - $start < $timeout or $timeout == -1)) { - $this->__process(); + while (!$this->disconnected + && $this->until_count[$event_key] < 1 + && ($timeout == -1 || time() - $start < $timeout) + ) { + $maximum = $timeout == -1 + ? NULL + : time() - $start; + $this->__process($maximum, true); } - if(array_key_exists($event_key, $this->until_payload)) { + + if (array_key_exists($event_key, $this->until_payload)) { $payload = $this->until_payload[$event_key]; unset($this->until_payload[$event_key]); unset($this->until_count[$event_key]); @@ -478,6 +502,7 @@ class XMPPHP_XMLStream { } else { $payload = array(); } + return $payload; } From b9a9fb85d782ea6b6f200daa880ec590bb7e388e Mon Sep 17 00:00:00 2001 From: Christian Weiske Date: Thu, 25 Feb 2010 02:53:13 +0800 Subject: [PATCH 2/3] we can receive messages of any length now, even > 4096 bytes --- XMPPHP/XMLStream.php | 77 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/XMPPHP/XMLStream.php b/XMPPHP/XMLStream.php index d9e99cc..63f3b4f 100644 --- a/XMPPHP/XMLStream.php +++ b/XMPPHP/XMLStream.php @@ -288,9 +288,12 @@ class XMPPHP_XMLStream { /** * Connect to XMPP Host * - * @param integer $timeout + * @param integer $timeout Timeout in seconds * @param boolean $persistent - * @param boolean $sendinit + * @param boolean $sendinit Send XMPP starting sequence after connect + * automatically + * + * @throws XMPPHP_Exception When the connection fails */ public function connect($timeout = 30, $persistent = false, $sendinit = true) { $this->sent_disconnect = false; @@ -330,6 +333,10 @@ class XMPPHP_XMLStream { /** * Reconnect XMPP Host + * + * @throws XMPPHP_Exception When the connection fails + * @uses $reconnectTimeout + * @see setReconnectTimeout() */ public function doReconnect() { if(!$this->is_server) { @@ -368,6 +375,41 @@ class XMPPHP_XMLStream { return $this->disconnected; } + /** + * Checks if the given string is closed with the same tag as it is + * opened. We try to be as fast as possible here. + * + * @param string $buff Read buffer of __process() + * + * @return boolean true if the buffer seems to be complete + */ + protected function bufferComplete($buff) + { + if (substr($buff, -1) != '>') { + return false; + } + //we always have a space since the namespace needs to be + //declared. could be a tab, though + $start = substr($buff, 1, strpos($buff, ' ', 2) - 1); + $stop = substr($buff, -strlen($start) - 3); + + if ($start == '?xml') { + //starting with an xml tag. this means a stream is being + // opened, which is not much of data, so no fear it's + // not complete + return true; + } + if (substr($stop, -2) == '/>') { + //one tag, i.e. + return true; + } + if ('' == $stop) { + return true; + } + + return false; + } + /** * Core reading tool * @@ -410,18 +452,22 @@ class XMPPHP_XMLStream { return false; } } else if ($updated > 0) { - # XXX: Is this big enough? - $buff = @fread($this->socket, 4096); - if(!$buff) { - if($this->reconnect) { - $this->doReconnect(); - } else { - fclose($this->socket); - $this->socket = NULL; - return false; + $buff = ''; + do { + $part = stream_socket_recvfrom($this->socket, 4096); + if (!$part) { + if($this->reconnect) { + $this->doReconnect(); + } else { + fclose($this->socket); + $this->socket = NULL; + return false; + } } - } - $this->log->log("RECV: $buff", XMPPHP_Log::LEVEL_VERBOSE); + $this->log->log("RECV: $part", XMPPHP_Log::LEVEL_VERBOSE); + $buff .= $part; + } while (!$this->bufferComplete($buff)); + xml_parse($this->parser, $buff, false); if ($return_when_received) { return true; @@ -491,7 +537,10 @@ class XMPPHP_XMLStream { $maximum = $timeout == -1 ? NULL : time() - $start; - $this->__process($maximum, true); + $ret = $this->__process($maximum, true); + if (!$ret) { + break; + } } if (array_key_exists($event_key, $this->until_payload)) { From fe80cd6f487100ed8bd3c2dde1331c44c77c52b2 Mon Sep 17 00:00:00 2001 From: Mat Gadd Date: Thu, 25 Feb 2010 15:51:04 +0000 Subject: [PATCH 3/3] Replace usage of deprecated split() function with explode(). --- XMPPHP/Roster.php | 4 ++-- XMPPHP/XMLStream.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/XMPPHP/Roster.php b/XMPPHP/Roster.php index 2e459e2..ccbf6c8 100644 --- a/XMPPHP/Roster.php +++ b/XMPPHP/Roster.php @@ -118,7 +118,7 @@ class Roster { * @param string $status */ public function setPresence($presence, $priority, $show, $status) { - list($jid, $resource) = split("/", $presence); + list($jid, $resource) = explode('/', $presence, 2); if ($show != 'unavailable') { if (!$this->isContact($jid)) { $this->addContact($jid, 'not-in-roster'); @@ -137,7 +137,7 @@ class Roster { * @param string $jid */ public function getPresence($jid) { - $split = split("/", $jid); + $split = explode('/', $jid, 2); $jid = $split[0]; if($this->isContact($jid)) { $current = array('resource' => '', 'active' => '', 'priority' => -129, 'show' => '', 'status' => ''); //Priorities can only be -128 = 127 diff --git a/XMPPHP/XMLStream.php b/XMPPHP/XMLStream.php index 63f3b4f..3e6e241 100644 --- a/XMPPHP/XMLStream.php +++ b/XMPPHP/XMLStream.php @@ -263,7 +263,7 @@ class XMPPHP_XMLStream { $ns_tags = array($xpath); } foreach($ns_tags as $ns_tag) { - list($l, $r) = split("}", $ns_tag); + list($l, $r) = explode('}', $ns_tag); if ($r != null) { $xpart = array(substr($l, 1), $r); } else {