1 | # -*- test-case-name: wokkel.test.test_compat -*- |
---|
2 | # |
---|
3 | # Copyright (c) 2001-2008 Twisted Matrix Laboratories. |
---|
4 | # See LICENSE for details. |
---|
5 | |
---|
6 | from twisted.internet import protocol |
---|
7 | from twisted.words.protocols.jabber import xmlstream |
---|
8 | from twisted.words.xish import domish |
---|
9 | |
---|
10 | def toResponse(stanza, stanzaType=None): |
---|
11 | """ |
---|
12 | Create a response stanza from another stanza. |
---|
13 | |
---|
14 | This takes the addressing and id attributes from a stanza to create a (new, |
---|
15 | empty) response stanza. The addressing attributes are swapped and the id |
---|
16 | copied. Optionally, the stanza type of the response can be specified. |
---|
17 | |
---|
18 | @param stanza: the original stanza |
---|
19 | @type stanza: L{domish.Element} |
---|
20 | @param stanzaType: optional response stanza type |
---|
21 | @type stanzaType: C{str} |
---|
22 | @return: the response stanza. |
---|
23 | @rtype: L{domish.Element} |
---|
24 | """ |
---|
25 | |
---|
26 | toAddr = stanza.getAttribute('from') |
---|
27 | fromAddr = stanza.getAttribute('to') |
---|
28 | stanzaID = stanza.getAttribute('id') |
---|
29 | |
---|
30 | response = domish.Element((None, stanza.name)) |
---|
31 | if toAddr: |
---|
32 | response['to'] = toAddr |
---|
33 | if fromAddr: |
---|
34 | response['from'] = fromAddr |
---|
35 | if stanzaID: |
---|
36 | response['id'] = stanzaID |
---|
37 | if stanzaType: |
---|
38 | response['type'] = stanzaType |
---|
39 | |
---|
40 | return response |
---|
41 | |
---|
42 | |
---|
43 | |
---|
44 | class BootstrapMixin(object): |
---|
45 | """ |
---|
46 | XmlStream factory mixin to install bootstrap event observers. |
---|
47 | |
---|
48 | This mixin is for factories providing |
---|
49 | L{IProtocolFactory<twisted.internet.interfaces.IProtocolFactory>} to make |
---|
50 | sure bootstrap event observers are set up on protocols, before incoming |
---|
51 | data is processed. Such protocols typically derive from |
---|
52 | L{utility.EventDispatcher}, like L{XmlStream}. |
---|
53 | |
---|
54 | You can set up bootstrap event observers using C{addBootstrap}. The |
---|
55 | C{event} and C{fn} parameters correspond with the C{event} and |
---|
56 | C{observerfn} arguments to L{utility.EventDispatcher.addObserver}. |
---|
57 | |
---|
58 | @since: 8.2. |
---|
59 | @ivar bootstraps: The list of registered bootstrap event observers. |
---|
60 | @type bootstrap: C{list} |
---|
61 | """ |
---|
62 | |
---|
63 | def __init__(self): |
---|
64 | self.bootstraps = [] |
---|
65 | |
---|
66 | |
---|
67 | def installBootstraps(self, dispatcher): |
---|
68 | """ |
---|
69 | Install registered bootstrap observers. |
---|
70 | |
---|
71 | @param dispatcher: Event dispatcher to add the observers to. |
---|
72 | @type dispatcher: L{utility.EventDispatcher} |
---|
73 | """ |
---|
74 | for event, fn in self.bootstraps: |
---|
75 | dispatcher.addObserver(event, fn) |
---|
76 | |
---|
77 | |
---|
78 | def addBootstrap(self, event, fn): |
---|
79 | """ |
---|
80 | Add a bootstrap event handler. |
---|
81 | |
---|
82 | @param event: The event to register an observer for. |
---|
83 | @type event: C{str} or L{xpath.XPathQuery} |
---|
84 | @param fn: The observer callable to be registered. |
---|
85 | """ |
---|
86 | self.bootstraps.append((event, fn)) |
---|
87 | |
---|
88 | |
---|
89 | def removeBootstrap(self, event, fn): |
---|
90 | """ |
---|
91 | Remove a bootstrap event handler. |
---|
92 | |
---|
93 | @param event: The event the observer is registered for. |
---|
94 | @type event: C{str} or L{xpath.XPathQuery} |
---|
95 | @param fn: The registered observer callable. |
---|
96 | """ |
---|
97 | self.bootstraps.remove((event, fn)) |
---|
98 | |
---|
99 | |
---|
100 | |
---|
101 | class XmlStreamServerFactory(BootstrapMixin, |
---|
102 | protocol.ServerFactory): |
---|
103 | """ |
---|
104 | Factory for Jabber XmlStream objects as a server. |
---|
105 | |
---|
106 | @since: 8.2. |
---|
107 | @ivar authenticatorFactory: Factory callable that takes no arguments, to |
---|
108 | create a fresh authenticator to be associated |
---|
109 | with the XmlStream. |
---|
110 | """ |
---|
111 | |
---|
112 | protocol = xmlstream.XmlStream |
---|
113 | |
---|
114 | def __init__(self, authenticatorFactory): |
---|
115 | BootstrapMixin.__init__(self) |
---|
116 | self.authenticatorFactory = authenticatorFactory |
---|
117 | |
---|
118 | |
---|
119 | def buildProtocol(self, addr): |
---|
120 | """ |
---|
121 | Create an instance of XmlStream. |
---|
122 | |
---|
123 | A new authenticator instance will be created and passed to the new |
---|
124 | XmlStream. Registered bootstrap event observers are installed as well. |
---|
125 | """ |
---|
126 | authenticator = self.authenticatorFactory() |
---|
127 | xs = self.protocol(authenticator) |
---|
128 | xs.factory = self |
---|
129 | self.installBootstraps(xs) |
---|
130 | return xs |
---|