source: wokkel/ping.py @ 65:6936acbdb9bd

Last change on this file since 65:6936acbdb9bd was 65:6936acbdb9bd, checked in by Ralph Meijer <ralphm@…>, 12 years ago

Add support for the XMPP Ping protocol.

Author: ralphm
Fixes #55.

This adds a whole bunch of examples around the ping protocol in different
settings for both the pinger and pingee: as a external server-side component,
as a standalone server with server-to-server connectivity and as a client.

Also updates the disco support to allow for non-deferred responses from
subprotocol handlers

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