]>
code.delx.au - pymsnt/blob - src/disco.py
1 # Copyright 2004 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
5 if(utils
.checkTwisted()):
6 from twisted
.xish
.domish
import Element
8 from tlib
.domish
import Element
9 from twisted
.internet
.defer
import Deferred
10 from twisted
.internet
import reactor
16 XMPP_STANZAS
= 'urn:ietf:params:xml:ns:xmpp-stanzas'
17 DISCO
= "http://jabber.org/protocol/disco"
18 DISCO_ITEMS
= DISCO
+ "#items"
19 DISCO_INFO
= DISCO
+ "#info"
22 class ServerDiscovery
:
23 def __init__ (self
, pytrans
):
24 debug
.log("Discovery: Created server discovery manager")
25 self
.pytrans
= pytrans
28 self
.deferredIqs
= {} # A dict indexed by (jid, id) of deferreds to fire
30 self
.addFeature(DISCO
, None)
32 def sendIq(self
, el
, timeout
=15):
33 """ Used for sending IQ packets.
34 The id attribute for the IQ will be autogenerated if it is not there yet.
35 Returns a deferred which will fire with the matching IQ response as it's sole argument. """
39 del self
.deferredIqs
[(jid
, ID
)]
41 jid
= el
.getAttribute("to")
42 ID
= el
.getAttribute("id")
44 ID
= self
.pytrans
.makeMessageID()
45 el
.attributes
["id"] = ID
48 self
.deferredIqs
[(jid
, ID
)] = d
49 reactor
.callLater(timeout
, checkDeferred
)
52 def addIdentity(self
, category
, ctype
, name
):
53 debug
.log("Discovery: Adding identitity \"%s\" \"%s\" \"%s\"" % (category
, ctype
, name
))
54 self
.identities
.append((category
, ctype
, name
))
56 def addFeature(self
, var
, handler
):
57 debug
.log("Discovery: Adding feature support \"%s\" \"%s\"" % (var
, handler
))
58 self
.features
.append((var
, handler
))
61 fro
= el
.getAttribute("from")
62 to
= el
.getAttribute("to")
63 ID
= el
.getAttribute("id")
64 iqType
= el
.getAttribute("type")
66 # Check if it's a response to a send IQ
67 if(self
.deferredIqs
.has_key((fro
, ID
)) and iqType
in ["error", "result"]):
68 self
.deferredIqs
[(fro
, ID
)].callback(el
)
69 del self
.deferredIqs
[(fro
, ID
)]
72 if(iqType
not in ["get", "set"]): return # Not interested
74 debug
.log("Discovery: Iq received \"%s\" \"%s\". Looking for handler" % (fro
, ID
))
76 for query
in el
.elements():
77 xmlns
= query
.defaultUri
79 if(to
.find('@') > 0): # Iq to a user
80 self
.sendIqNotSupported(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=DISCO
)
82 else: # Iq to transport
83 if(xmlns
== DISCO_INFO
):
84 self
.sendDiscoInfoResponse(to
=fro
, ID
=ID
)
85 elif(xmlns
== DISCO_ITEMS
):
86 self
.sendDiscoItemsResponse(to
=fro
, ID
=ID
)
89 for (feature
, handler
) in self
.features
:
90 if(feature
== xmlns
and handler
):
91 debug
.log("Discovery: Handler found \"%s\" \"%s\"" % (feature
, handler
))
95 debug
.log("Discovery: Unknown Iq request \"%s\" \"%s\" \"%s\"" % (fro
, ID
, xmlns
))
96 self
.sendIqNotSupported(to
=fro
, fro
=config
.jid
, ID
=ID
, xmlns
=DISCO
)
98 def sendDiscoInfoResponse(self
, to
, ID
):
99 debug
.log("Discovery: Replying to disco#info request from \"%s\" \"%s\"" % (to
, ID
))
100 iq
= Element((None, "iq"))
101 iq
.attributes
["type"] = "result"
102 iq
.attributes
["from"] = config
.jid
103 iq
.attributes
["to"] = to
105 iq
.attributes
["id"] = ID
106 query
= iq
.addElement("query")
107 query
.attributes
["xmlns"] = DISCO_INFO
110 for (category
, ctype
, name
) in self
.identities
:
111 identity
= query
.addElement("identity")
112 identity
.attributes
["category"] = category
113 identity
.attributes
["type"] = ctype
114 identity
.attributes
["name"] = name
116 # Add any supported features
117 for (var
, handler
) in self
.features
:
118 feature
= query
.addElement("feature")
119 feature
.attributes
["var"] = var
120 self
.pytrans
.send(iq
)
122 def sendDiscoItemsResponse(self
, to
, ID
):
123 debug
.log("Discovery: Replying to disco#items request from \"%s\" \"%s\"" % (to
, ID
))
124 iq
= Element((None, "iq"))
125 iq
.attributes
["type"] = "result"
126 iq
.attributes
["from"] = config
.jid
127 iq
.attributes
["to"] = to
129 iq
.attributes
["id"] = ID
130 query
= iq
.addElement("query")
131 query
.attributes
["xmlns"] = DISCO_ITEMS
133 self
.pytrans
.send(iq
)
136 def sendIqNotSupported(self
, to
, fro
, ID
, xmlns
):
137 debug
.log("Discovery: Replying with error to unknown Iq request")
138 iq
= Element((None, "iq"))
139 iq
.attributes
["type"] = "error"
140 iq
.attributes
["from"] = fro
141 iq
.attributes
["to"] = to
143 iq
.attributes
["id"] = ID
144 error
= iq
.addElement("error")
145 error
.attributes
["xmlns"] = xmlns
146 error
.attributes
["type"] = "cancel"
147 error
.attributes
["xmlns"] = XMPP_STANZAS
148 text
= error
.addElement("text")
149 text
.attributes
["xmlns"] = XMPP_STANZAS
150 text
.addContent("Not implemented.")
152 self
.pytrans
.send(iq
)
154 def sendIqNotValid(self
, to
, ID
, xmlns
):
155 debug
.log("Discovery: Replying with error to invalid Iq request")
156 iq
= Element((None, "iq"))
157 iq
.attributes
["type"] = "error"
158 iq
.attributes
["from"] = config
.jid
159 iq
.attributes
["to"] = to
161 iq
.attributes
["id"] = ID
162 error
= iq
.addElement("error")
163 error
.attributes
["xmlns"] = xmlns
164 error
.attributes
["type"] = "modify"
165 error
.attributes
["xmlns"] = XMPP_STANZAS
166 text
= error
.addElement("text")
167 text
.attributes
["xmlns"] = XMPP_STANZAS
168 text
.addContent("Not valid.")
170 self
.pytrans
.send(iq
)