Updated XEP-0199 to take and return standardized values.

Handles Iq errors appropriately when the recipient can't be found.
This commit is contained in:
Lance Stout 2013-01-20 20:14:16 -08:00
parent 1f9286d39e
commit 3423589ba1
2 changed files with 87 additions and 80 deletions

View File

@ -62,16 +62,18 @@ class PingTest(sleekxmpp.ClientXMPP):
""" """
self.send_presence() self.send_presence()
self.get_roster() self.get_roster()
result = self['xep_0199'].send_ping(self.pingjid,
timeout=10, try:
errorfalse=True) rtt = self['xep_0199'].ping(self.pingjid,
logging.info("Pinging...") timeout=10)
if result is False: logging.info("Success! RTT: %s", rtt)
logging.info("Couldn't ping.") except IqError as e:
self.disconnect() logging.info("Error pinging %s: %s",
sys.exit(1) self.pingjid,
else: e.iq['error']['condition'])
logging.info("Success! RTT: %s", str(result)) except IqTimeout:
logging.info("No response from %s", self.pingjid)
finally:
self.disconnect() self.disconnect()

View File

@ -9,8 +9,8 @@
import time import time
import logging import logging
import sleekxmpp from sleekxmpp.jid import JID
from sleekxmpp import Iq from sleekxmpp.stanza import Iq
from sleekxmpp.exceptions import IqError, IqTimeout from sleekxmpp.exceptions import IqError, IqTimeout
from sleekxmpp.xmlstream import register_stanza_plugin from sleekxmpp.xmlstream import register_stanza_plugin
from sleekxmpp.xmlstream.matcher import StanzaPath from sleekxmpp.xmlstream.matcher import StanzaPath
@ -38,7 +38,7 @@ class XEP_0199(BasePlugin):
keepalive -- If True, periodically send ping requests keepalive -- If True, periodically send ping requests
to the server. If a ping is not answered, to the server. If a ping is not answered,
the connection will be reset. the connection will be reset.
frequency -- Time in seconds between keepalive pings. interval -- Time in seconds between keepalive pings.
Defaults to 300 seconds. Defaults to 300 seconds.
timeout -- Time in seconds to wait for a ping response. timeout -- Time in seconds to wait for a ping response.
Defaults to 30 seconds. Defaults to 30 seconds.
@ -53,7 +53,7 @@ class XEP_0199(BasePlugin):
stanza = stanza stanza = stanza
default_config = { default_config = {
'keepalive': False, 'keepalive': False,
'frequency': 300, 'interval': 300,
'timeout': 30 'timeout': 30
} }
@ -61,6 +61,7 @@ class XEP_0199(BasePlugin):
""" """
Start the XEP-0199 plugin. Start the XEP-0199 plugin.
""" """
register_stanza_plugin(Iq, Ping) register_stanza_plugin(Iq, Ping)
self.xmpp.register_handler( self.xmpp.register_handler(
@ -70,88 +71,70 @@ class XEP_0199(BasePlugin):
if self.keepalive: if self.keepalive:
self.xmpp.add_event_handler('session_start', self.xmpp.add_event_handler('session_start',
self._handle_keepalive, self.enable_keepalive,
threaded=True) threaded=True)
self.xmpp.add_event_handler('session_end', self.xmpp.add_event_handler('session_end',
self._handle_session_end) self.disable_keepalive)
def plugin_end(self): def plugin_end(self):
self.xmpp['xep_0030'].del_feature(feature=Ping.namespace) self.xmpp['xep_0030'].del_feature(feature=Ping.namespace)
self.xmpp.remove_handler('Ping') self.xmpp.remove_handler('Ping')
if self.keepalive: if self.keepalive:
self.xmpp.del_event_handler('session_start', self.xmpp.del_event_handler('session_start',
self._handle_keepalive) self.enable_keepalive)
self.xmpp.del_event_handler('session_end', self.xmpp.del_event_handler('session_end',
self._handle_session_end) self.disable_keepalive)
def session_bind(self, jid): def session_bind(self, jid):
self.xmpp['xep_0030'].add_feature(Ping.namespace) self.xmpp['xep_0030'].add_feature(Ping.namespace)
def _handle_keepalive(self, event): def enable_keepalive(self, interval=None, timeout=None):
""" if interval:
Begin periodic pinging of the server. If a ping is not self.interval = interval
answered, the connection will be restarted. if timeout:
self.timeout = timeout
The pinging interval can be adjused using self.frequency self.keepalive = True
before beginning processing. self.xmpp.schedule('Ping keepalive',
self.interval,
self._keepalive,
repeat=True)
Arguments: def disable_keepalive(self, event=None):
event -- The session_start event. self.xmpp.scheduler.remove('Ping keepalive')
"""
def scheduled_ping(): def _keepalive(self, event):
"""Send ping request to the server.""" log.debug("Keepalive ping...")
log.debug("Pinging...")
try: try:
self.send_ping(self.xmpp.boundjid.host, self.timeout) rtt = self.ping(self.xmpp.boundjid.host, self.timeout)
except IqError:
log.debug("Ping response was an error." + \
"Requesting Reconnect.")
self.xmpp.reconnect()
except IqTimeout: except IqTimeout:
log.debug("Did not recieve ping back in time." + \ log.debug("Did not recieve ping back in time." + \
"Requesting Reconnect.") "Requesting Reconnect.")
self.xmpp.reconnect() self.xmpp.reconnect()
else:
self.xmpp.schedule('Ping Keep Alive', log.debug('Keepalive RTT: %s' % rtt)
self.frequency,
scheduled_ping,
repeat=True)
def _handle_session_end(self, event):
self.xmpp.scheduler.remove('Ping Keep Alive')
def _handle_ping(self, iq): def _handle_ping(self, iq):
""" """Automatically reply to ping requests."""
Automatically reply to ping requests.
Arguments:
iq -- The ping request.
"""
log.debug("Pinged by %s", iq['from']) log.debug("Pinged by %s", iq['from'])
iq.reply().send() iq.reply().send()
def send_ping(self, jid, timeout=None, errorfalse=False, def send_ping(self, jid, ifrom=None, block=True, timeout=None, callback=None):
ifrom=None, block=True, callback=None): """Send a ping request.
"""
Send a ping request and calculate the response time.
Arguments: Arguments:
jid -- The JID that will receive the ping. jid -- The JID that will receive the ping.
timeout -- Time in seconds to wait for a response.
Defaults to self.timeout.
errorfalse -- Indicates if False should be returned
if an error stanza is received. Defaults
to False.
ifrom -- Specifiy the sender JID. ifrom -- Specifiy the sender JID.
block -- Indicate if execution should block until block -- Indicate if execution should block until
a pong response is received. Defaults a pong response is received. Defaults
to True. to True.
timeout -- Time in seconds to wait for a response.
Defaults to self.timeout.
callback -- Optional handler to execute when a pong callback -- Optional handler to execute when a pong
is received. Useful in conjunction with is received. Useful in conjunction with
the option block=False. the option block=False.
""" """
log.debug("Pinging %s", jid) if not timeout:
if timeout is None:
timeout = self.timeout timeout = self.timeout
iq = self.xmpp.Iq() iq = self.xmpp.Iq()
@ -160,21 +143,43 @@ class XEP_0199(BasePlugin):
iq['from'] = ifrom iq['from'] = ifrom
iq.enable('ping') iq.enable('ping')
start_time = time.clock() return iq.send(block=block, timeout=timeout, callback=callback)
def ping(self, jid=None, ifrom=None, timeout=None):
"""Send a ping request and calculate RTT.
Arguments:
jid -- The JID that will receive the ping.
ifrom -- Specifiy the sender JID.
timeout -- Time in seconds to wait for a response.
Defaults to self.timeout.
"""
if not jid:
if self.xmpp.is_component:
jid = self.xmpp.server
else:
jid = self.xmpp.boundjid.host
jid = JID(jid)
if jid == self.xmpp.boundjid.host or \
self.xmpp.is_component and jid == self.xmpp.server:
own_host = True
if not timeout:
timeout = self.timeout
start = time.time()
log.debug('Pinging %s' % jid)
try: try:
resp = iq.send(block=block, self.send_ping(jid, ifrom=ifrom, timeout=timeout)
timeout=timeout, except IqError as e:
callback=callback) if own_host:
except IqError as err: rtt = time.time() - start
resp = err.iq log.debug('Pinged %s, RTT: %s', jid, rtt)
return rtt
end_time = time.clock() else:
raise e
delay = end_time - start_time else:
rtt = time.time() - start
if not block: log.debug('Pinged %s, RTT: %s', jid, rtt)
return None return rtt
log.debug("Pong: %s %f", jid, delay)
return delay