comparison sat.tac @ 16:0a024d5e0cd0

New account creation (in-band registration) - new method "sendAnswer" in bridge for asyncronous result communication
author Goffi <goffi@goffi.org>
date Mon, 02 Nov 2009 00:45:03 +0100
parents 218ec9984fa5
children 74a39f40eb6d
comparison
equal deleted inserted replaced
15:218ec9984fa5 16:0a024d5e0cd0
18 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """ 20 """
21 21
22 client_name = u'SàT (Salut à toi)' 22 client_name = u'SàT (Salut à toi)'
23 client_version = '0.0.1' 23 client_version = '0.0.1D' #Please add 'D' at the end for dev versions
24 24
25 from twisted.application import internet, service 25 from twisted.application import internet, service
26 from twisted.internet import glib2reactor, protocol, task 26 from twisted.internet import glib2reactor, protocol, task
27 glib2reactor.install() 27 glib2reactor.install()
28 28
30 from twisted.words.xish import domish 30 from twisted.words.xish import domish
31 31
32 from twisted.internet import reactor 32 from twisted.internet import reactor
33 import pdb 33 import pdb
34 34
35 from wokkel import client, disco, xmppim, generic 35 from wokkel import client, disco, xmppim, generic, compat
36 36
37 from sat_bridge.DBus import DBusBridge 37 from sat_bridge.DBus import DBusBridge
38 import logging 38 import logging
39 from logging import debug, info, error 39 from logging import debug, info, error
40 40
53 ### logging configuration FIXME: put this elsewhere ### 53 ### logging configuration FIXME: put this elsewhere ###
54 logging.basicConfig(level=logging.DEBUG, 54 logging.basicConfig(level=logging.DEBUG,
55 format='%(message)s') 55 format='%(message)s')
56 ### 56 ###
57 57
58
59 sat_id = 0
60
61 def sat_next_id():
62 global sat_id
63 sat_id+=1
64 return "sat_id_"+str(sat_id)
58 65
59 class SatXMPPClient(client.XMPPClient): 66 class SatXMPPClient(client.XMPPClient):
60 67
61 def __init__(self, jid, password, host=None, port=5222): 68 def __init__(self, jid, password, host=None, port=5222):
62 client.XMPPClient.__init__(self, jid, password, host, port) 69 client.XMPPClient.__init__(self, jid, password, host, port)
185 192
186 def iqFallback(self, iq): 193 def iqFallback(self, iq):
187 #pdb.set_trace() 194 #pdb.set_trace()
188 print "iqFallback: xml = [%s], handled=%s" % (iq.toXml(), "True" if iq.handled else "False") 195 print "iqFallback: xml = [%s], handled=%s" % (iq.toXml(), "True" if iq.handled else "False")
189 generic.FallbackHandler.iqFallback(self, iq) 196 generic.FallbackHandler.iqFallback(self, iq)
190 197
198 class RegisteringAuthenticator(xmlstream.ConnectAuthenticator):
199
200 def __init__(self, host, jabber_host, user_login, user_pass, answer_id):
201 xmlstream.ConnectAuthenticator.__init__(self, jabber_host)
202 self.host = host
203 self.jabber_host = jabber_host
204 self.user_login = user_login
205 self.user_pass = user_pass
206 self.answer_id = answer_id
207
208 def connectionMade(self):
209 print "connectionMade"
210
211 self.xmlstream.namespace = "jabber:client"
212 self.xmlstream.sendHeader()
213
214 iq = compat.IQ(self.xmlstream, 'set')
215 iq["to"] = self.jabber_host
216 query = iq.addElement(('jabber:iq:register', 'query'))
217 _user = query.addElement('username')
218 _user.addContent(self.user_login)
219 _pass = query.addElement('password')
220 _pass.addContent(self.user_pass)
221 reg = iq.send(self.jabber_host).addCallbacks(self.registrationAnswer, self.registrationFailure)
222
223 def registrationAnswer(self, answer):
224 debug ("registration answer: %s" % answer.toXml())
225 answer_type = "success"
226 answer_data={"human":"Registration successfull"}
227 self.host.bridge.sendAnswer(answer_type, self.answer_id, answer_data)
228 self.xmlstream.sendFooter()
229
230 def registrationFailure(self, error):
231 info ("Registration failure: %s" %str(error))
232 answer_type = "error"
233 answer_data={"human":"Registration failed"}
234 if error.value.condition == 'conflict':
235 answer_data['reason'] = 'conflict'
236 else:
237 answer_data['reason'] = 'unknown'
238 self.host.bridge.sendAnswer(answer_type, self.answer_id, answer_data)
239 self.xmlstream.sendFooter()
240
191 241
192 class SAT(service.Service): 242 class SAT(service.Service):
193 243
194 def __init__(self): 244 def __init__(self):
195 #self.reactor=reactor 245 #self.reactor=reactor
199 self._waiting_conf = {} #callback called when a confirmation is received 249 self._waiting_conf = {} #callback called when a confirmation is received
200 self._progress_cb_map = {} #callback called when a progress is requested (key = progress id) 250 self._progress_cb_map = {} #callback called when a progress is requested (key = progress id)
201 self.plugins = {} 251 self.plugins = {}
202 252
203 self.bridge=DBusBridge() 253 self.bridge=DBusBridge()
254 self.bridge.register("registerNewAccount", self.registerNewAccount)
204 self.bridge.register("connect", self.connect) 255 self.bridge.register("connect", self.connect)
205 self.bridge.register("disconnect", self.disconnect) 256 self.bridge.register("disconnect", self.disconnect)
206 self.bridge.register("getContacts", self.memory.getContacts) 257 self.bridge.register("getContacts", self.memory.getContacts)
207 self.bridge.register("getPresenceStatus", self.memory.getPresenceStatus) 258 self.bridge.register("getPresenceStatus", self.memory.getPresenceStatus)
208 self.bridge.register("sendMessage", self.sendMessage) 259 self.bridge.register("sendMessage", self.sendMessage)
217 self.bridge.register("isConnected", self.isConnected) 268 self.bridge.register("isConnected", self.isConnected)
218 self.bridge.register("confirmationAnswer", self.confirmationAnswer) 269 self.bridge.register("confirmationAnswer", self.confirmationAnswer)
219 self.bridge.register("getProgress", self.getProgress) 270 self.bridge.register("getProgress", self.getProgress)
220 271
221 self._import_plugins() 272 self._import_plugins()
222 #self.connect()
223 273
224 274
225 def _import_plugins(self): 275 def _import_plugins(self):
226 """Import all plugins found in plugins directory""" 276 """Import all plugins found in plugins directory"""
227 #TODO: manage dependencies 277 #TODO: manage dependencies
232 __import__(plug_path) 282 __import__(plug_path)
233 mod = sys.modules[plug_path] 283 mod = sys.modules[plug_path]
234 plug_info = mod.PLUGIN_INFO 284 plug_info = mod.PLUGIN_INFO
235 info ("importing plugin: %s", plug_info['name']) 285 info ("importing plugin: %s", plug_info['name'])
236 self.plugins[plug_info['import_name']] = getattr(mod, plug_info['main'])(self) 286 self.plugins[plug_info['import_name']] = getattr(mod, plug_info['main'])(self)
287 #TODO: test xmppclient presence and register handler parent
237 288
238 def connect(self): 289 def connect(self):
290 """Connect to jabber server"""
291
239 if (self.isConnected()): 292 if (self.isConnected()):
240 info("already connected !") 293 info("already connected !")
241 return 294 return
242 print "connecting..." 295 print "connecting..."
243 self.me = jid.JID(self.memory.getParamV("JabberID", "Connection")) 296 self.me = jid.JID(self.memory.getParamV("JabberID", "Connection"))
262 315
263 debug ("setting plugins parents") 316 debug ("setting plugins parents")
264 for plugin in self.plugins.iteritems(): 317 for plugin in self.plugins.iteritems():
265 if isinstance(plugin[1], XMPPHandler): 318 if isinstance(plugin[1], XMPPHandler):
266 plugin[1].setHandlerParent(self.xmppclient) 319 plugin[1].setHandlerParent(self.xmppclient)
267 320
268 self.xmppclient.startService() 321 self.xmppclient.startService()
269 322
270 def disconnect(self): 323 def disconnect(self):
324 """disconnect from jabber server"""
271 if (not self.isConnected()): 325 if (not self.isConnected()):
272 info("not connected !") 326 info("not connected !")
273 return 327 return
274 info("Disconnecting...") 328 info("Disconnecting...")
275 self.xmppclient.stopService() 329 self.xmppclient.stopService()
305 self.roster.requestRoster() 359 self.roster.requestRoster()
306 360
307 self.presence.available() 361 self.presence.available()
308 362
309 self.disco.requestInfo(jid.JID(self.memory.getParamV("Server", "Connection"))).addCallback(self.serverDisco) 363 self.disco.requestInfo(jid.JID(self.memory.getParamV("Server", "Connection"))).addCallback(self.serverDisco)
310 364
311 365 ## Misc methods ##
366
367 def registerNewAccount(self, login, password, server, port = 5222):
368 """Connect to a server and create a new account using in-band registration"""
369
370 next_id = sat_next_id() #the id is used to send server's answer
371 serverRegistrer = xmlstream.XmlStreamFactory(RegisteringAuthenticator(self, server, login, password, next_id))
372 connector = reactor.connectTCP(server, port, serverRegistrer)
373 serverRegistrer.clientConnectionLost = lambda conn, reason: connector.disconnect()
374
375 return next_id
376
377 ## Client management ##
378
379 def setParam(self, name, value, namespace):
380 """set wanted paramater and notice observers"""
381 info ("setting param: %s=%s in namespace %s", name, value, namespace)
382 self.memory.setParam(name, value, namespace)
383 self.bridge.paramUpdate(name, value, namespace)
384
385 def failed(self,xmlstream):
386 debug("failed: %s", xmlstream.getErrorMessage())
387 debug("failed: %s", dir(xmlstream))
388
389 def isConnected(self):
390 try:
391 if self.xmppclient.isConnected():
392 return True
393 except AttributeError:
394 #xmppclient not available
395 pass
396 return False
397
398 ## jabber methods ##
399
312 def sendMessage(self,to,msg,type='chat'): 400 def sendMessage(self,to,msg,type='chat'):
313 #FIXME: check validity of recipient 401 #FIXME: check validity of recipient
314 debug("Sending jabber message to %s...", to) 402 debug("Sending jabber message to %s...", to)
315 message = domish.Element(('jabber:client','message')) 403 message = domish.Element(('jabber:client','message'))
316 message["to"] = jid.JID(to).full() 404 message["to"] = jid.JID(to).full()
319 message.addElement("body", "jabber:client", msg) 407 message.addElement("body", "jabber:client", msg)
320 self.xmlstream.send(message) 408 self.xmlstream.send(message)
321 self.memory.addToHistory(self.me, self.me, jid.JID(to), message["type"], unicode(msg)) 409 self.memory.addToHistory(self.me, self.me, jid.JID(to), message["type"], unicode(msg))
322 self.bridge.newMessage(message['from'], unicode(msg), to=message['to']) #We send back the message, so all clients are aware of it 410 self.bridge.newMessage(message['from'], unicode(msg), to=message['to']) #We send back the message, so all clients are aware of it
323 411
324 def setParam(self, name, value, namespace):
325 """set wanted paramater and notice observers"""
326 info ("setting param: %s=%s in namespace %s", name, value, namespace)
327 self.memory.setParam(name, value, namespace)
328 self.bridge.paramUpdate(name, value, namespace)
329
330 def failed(self,xmlstream):
331 debug("failed: %s", xmlstream.getErrorMessage())
332 debug("failed: %s", dir(xmlstream))
333
334 def isConnected(self):
335 try:
336 if self.xmppclient.isConnected():
337 return True
338 except AttributeError:
339 #xmppclient not available
340 pass
341 return False
342
343 ## jabber methods ##
344 412
345 def setPresence(self, to="", type="", show="", status="", priority=0): 413 def setPresence(self, to="", type="", show="", status="", priority=0):
346 """Send our presence information""" 414 """Send our presence information"""
347 if not type in ["", "unavailable", "subscribed", "subscribe", 415 if not type in ["", "unavailable", "subscribed", "subscribe",
348 "unsubscribe", "unsubscribed", "prob", "error"]: 416 "unsubscribe", "unsubscribed", "prob", "error"]: