1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
# -*- test-case-name: tx_xmpp.test.test.test_ping -*-
#
# Copyright (c) Ralph Meijer.
# See LICENSE for details.
"""
XMPP Ping.
The XMPP Ping protocol is documented in
U{XEP-0199<http://xmpp.org/extensions/xep-0199.html>}.
"""
from __future__ import division, absolute_import
from zope.interface import implementer
from twisted.words.protocols.jabber.error import StanzaError
from twisted.words.protocols.jabber.xmlstream import IQ, toResponse
from twisted.words.protocols.jabber.xmlstream import XMPPHandler
from . import disco, itx_xmpp
NS_PING = "urn:xmpp:ping"
PING_REQUEST = "/iq[@type='get']/ping[@xmlns='%s']" % NS_PING
class PingClientProtocol(XMPPHandler):
"""
Ping client.
This handler implements the protocol for sending out XMPP Ping requests.
"""
def ping(self, entity, sender=None):
"""
Send out a ping request and wait for a response.
@param entity: Entity to be pinged.
@type entity: L{JID<twisted.words.protocols.jabber.jid.JID>}
@return: A deferred that fires upon receiving a response.
@rtype: L{Deferred<twisted.internet.defer.Deferred>}
@param sender: Optional sender address.
@type sender: L{JID<twisted.words.protocols.jabber.jid.JID>}
"""
def cb(response):
return None
def eb(failure):
failure.trap(StanzaError)
exc = failure.value
if exc.condition == "service-unavailable":
return None
else:
return failure
request = IQ(self.xmlstream, "get")
request.addElement((NS_PING, "ping"))
if sender is not None:
request["from"] = sender.full()
d = request.send(entity.full())
d.addCallbacks(cb, eb)
return d
@implementer(itx_xmpp.IDisco)
class PingHandler(XMPPHandler):
"""
Ping responder.
This handler waits for XMPP Ping requests and sends a response.
"""
def connectionInitialized(self):
"""
Called when the XML stream has been initialized.
This sets up an observer for incoming ping requests.
"""
self.xmlstream.addObserver(PING_REQUEST, self.onPing)
def onPing(self, iq):
"""
Called when a ping request has been received.
This immediately replies with a result response.
"""
response = toResponse(iq, "result")
self.xmlstream.send(response)
iq.handled = True
def getDiscoInfo(self, requestor, target, nodeIdentifier=""):
"""
Get identity and features from this entity, node.
This handler supports XMPP Ping, but only without a nodeIdentifier
specified.
"""
if not nodeIdentifier:
return [disco.DiscoFeature(NS_PING)]
else:
return []
def getDiscoItems(self, requestor, target, nodeIdentifier=""):
"""
Get contained items for this entity, node.
This handler does not support items.
"""
return []
|