comparison sat.tac @ 62:93cb45a7420f

SàT multi-profile: connection using profiles - /!\ plugins are temporarly deactivated
author Goffi <goffi@goffi.org>
date Fri, 29 Jan 2010 13:55:41 +1100
parents 9764e027ecc0
children 0db25931b60d
comparison
equal deleted inserted replaced
61:58d49fc19639 62:93cb45a7420f
68 sat_id+=1 68 sat_id+=1
69 return "sat_id_"+str(sat_id) 69 return "sat_id_"+str(sat_id)
70 70
71 class SatXMPPClient(client.XMPPClient): 71 class SatXMPPClient(client.XMPPClient):
72 72
73 def __init__(self, bridge, user_jid, password, host=None, port=5222): 73 def __init__(self, bridge, profile, user_jid, password, host=None, port=5222):
74 client.XMPPClient.__init__(self, user_jid, password, host, port) 74 client.XMPPClient.__init__(self, user_jid, password, host, port)
75 self.factory.clientConnectionLost = self.connectionLost 75 self.factory.clientConnectionLost = self.connectionLost
76 self.__connected=False 76 self.__connected=False
77 self.bridge = bridge 77 self.bridge = bridge
78 self.profile = profile
78 79
79 def _authd(self, xmlstream): 80 def _authd(self, xmlstream):
80 print "SatXMPPClient" 81 print "SatXMPPClient"
81 client.XMPPClient._authd(self, xmlstream) 82 client.XMPPClient._authd(self, xmlstream)
82 self.__connected=True 83 self.__connected=True
84 self.streamInitialized() 85 self.streamInitialized()
85 self.bridge.connected() #we send the signal to the clients 86 self.bridge.connected() #we send the signal to the clients
86 87
87 def streamInitialized(self): 88 def streamInitialized(self):
88 """Called after _authd""" 89 """Called after _authd"""
90 debug ("XML stream is initialized")
89 self.keep_alife = task.LoopingCall(self.xmlstream.send, " ") #Needed to avoid disconnection (specially with openfire) 91 self.keep_alife = task.LoopingCall(self.xmlstream.send, " ") #Needed to avoid disconnection (specially with openfire)
90 self.keep_alife.start(180) 92 self.keep_alife.start(180)
93
94 self.disco = SatDiscoProtocol(self)
95 self.disco.setHandlerParent(self)
96 self.discoHandler = disco.DiscoHandler()
97 self.discoHandler.setHandlerParent(self)
98
99 self.roster.requestRoster()
100
101 self.presence.available()
102
103 #self.disco.requestInfo(jid.JID(self.memory.getParamA("Server", "Connection"))).addCallback(self.host.serverDisco) #gof: FIXME
104
91 105
92 def isConnected(self): 106 def isConnected(self):
93 return self.__connected 107 return self.__connected
94 108
95 def connectionLost(self, connector, unused_reason): 109 def connectionLost(self, connector, unused_reason):
111 def onMessage(self, message): 125 def onMessage(self, message):
112 debug (u"got_message from: %s", message["from"]) 126 debug (u"got_message from: %s", message["from"])
113 for e in message.elements(): 127 for e in message.elements():
114 if e.name == "body": 128 if e.name == "body":
115 self.host.bridge.newMessage(message["from"], e.children[0]) 129 self.host.bridge.newMessage(message["from"], e.children[0])
116 self.host.memory.addToHistory(self.host.me, jid.JID(message["from"]), self.host.me, "chat", e.children[0]) 130 self.host.memory.addToHistory(self.parent.jid, jid.JID(message["from"]), self.parent.jid, "chat", e.children[0])
117 break 131 break
118 132
119 class SatRosterProtocol(xmppim.RosterClientProtocol): 133 class SatRosterProtocol(xmppim.RosterClientProtocol):
120 134
121 def __init__(self, host): 135 def __init__(self, host):
304 318
305 self.__waiting_conf = {} #callback called when a confirmation is received 319 self.__waiting_conf = {} #callback called when a confirmation is received
306 self.__progress_cb_map = {} #callback called when a progress is requested (key = progress id) 320 self.__progress_cb_map = {} #callback called when a progress is requested (key = progress id)
307 self.__general_cb_map = {} #callback called for general reasons (key = name) 321 self.__general_cb_map = {} #callback called for general reasons (key = name)
308 self.__private_data = {} #used for internal callbacks (key = id) 322 self.__private_data = {} #used for internal callbacks (key = id)
323 self.profiles = {}
309 self.plugins = {} 324 self.plugins = {}
310 325
311 self.memory=Memory(self) 326 self.memory=Memory(self)
312 self.server_features=[] #XXX: temp dic, need to be transfered into self.memory in the future 327 self.server_features=[] #XXX: temp dic, need to be transfered into self.memory in the future
313 328
334 self.bridge.register("isConnected", self.isConnected) 349 self.bridge.register("isConnected", self.isConnected)
335 self.bridge.register("launchAction", self.launchAction) 350 self.bridge.register("launchAction", self.launchAction)
336 self.bridge.register("confirmationAnswer", self.confirmationAnswer) 351 self.bridge.register("confirmationAnswer", self.confirmationAnswer)
337 self.bridge.register("getProgress", self.getProgress) 352 self.bridge.register("getProgress", self.getProgress)
338 353
339 self._import_plugins() 354 #self._import_plugins() #gof:
340 355
341 356
342 def _import_plugins(self): 357 def _import_plugins(self):
343 """Import all plugins found in plugins directory""" 358 """Import all plugins found in plugins directory"""
344 #TODO: manage dependencies 359 #TODO: manage dependencies
351 plug_info = mod.PLUGIN_INFO 366 plug_info = mod.PLUGIN_INFO
352 info ("importing plugin: %s", plug_info['name']) 367 info ("importing plugin: %s", plug_info['name'])
353 self.plugins[plug_info['import_name']] = getattr(mod, plug_info['main'])(self) 368 self.plugins[plug_info['import_name']] = getattr(mod, plug_info['main'])(self)
354 #TODO: test xmppclient presence and register handler parent 369 #TODO: test xmppclient presence and register handler parent
355 370
356 def getJidFrProfile(self, profile): 371 def connect(self, profile_key = '@DEFAULT@'):
357 """Return jid from source"""
358 if profile == "@DEFAULT@":
359 return jid.JID(self.memory.getParamA("JabberID", "Connection"))
360
361 def connect(self, profile = '@DEFAULT@'):
362 """Connect to jabber server""" 372 """Connect to jabber server"""
363 373
374
375 profile = self.memory.getProfileName(profile_key)
376 if not profile_key:
377 error ('Trying to connect a non-exsitant profile')
378 return
379
364 if (self.isConnected()): 380 if (self.isConnected()):
365 info("already connected !") 381 info("already connected !")
366 return 382 return
367 print "connecting..." 383 print "connecting..."
368 self.me = self.getJidFrProfile(profile) 384 current = self.profiles[profile] = SatXMPPClient(self.bridge, profile,
369 self.xmppclient = SatXMPPClient(self.bridge, self.me, self.memory.getParamA("Password", "Connection"), 385 jid.JID(self.memory.getParamA("JabberID", "Connection"), profile),
386 self.memory.getParamA("Password", "Connection"),
370 self.memory.getParamA("Server", "Connection"), 5222) 387 self.memory.getParamA("Server", "Connection"), 5222)
371 self.xmppclient.streamInitialized = self.streamInitialized 388
372 389 #current.client.streamInitialized = self.streamInitialized #gof:
373 self.messageProt = SatMessageProtocol(self) 390
374 self.messageProt.setHandlerParent(self.xmppclient) 391 current.messageProt = SatMessageProtocol(self)
375 392 current.messageProt.setHandlerParent(current)
376 self.roster = SatRosterProtocol(self) 393
377 self.roster.setHandlerParent(self.xmppclient) 394 current.roster = SatRosterProtocol(self)
378 395 current.roster.setHandlerParent(current)
379 self.presence = SatPresenceProtocol(self) 396
380 self.presence.setHandlerParent(self.xmppclient) 397 current.presence = SatPresenceProtocol(self)
381 398 current.presence.setHandlerParent(current)
382 self.fallBack = SatFallbackHandler(self) 399
383 self.fallBack.setHandlerParent(self.xmppclient) 400 current.fallBack = SatFallbackHandler(self)
384 401 current.fallBack.setHandlerParent(current)
385 self.versionHandler = generic.VersionHandler(self.get_const('client_name'), 402
403 current.versionHandler = generic.VersionHandler(self.get_const('client_name'),
386 self.get_const('client_version')) 404 self.get_const('client_version'))
387 self.versionHandler.setHandlerParent(self.xmppclient) 405 current.versionHandler.setHandlerParent(current)
388 406
389 debug ("setting plugins parents") 407 debug ("setting plugins parents")
408
409 #FIXME: gof
390 for plugin in self.plugins.iteritems(): 410 for plugin in self.plugins.iteritems():
391 if isinstance(plugin[1], XMPPHandler): 411 if isinstance(plugin[1], XMPPHandler):
392 plugin[1].setHandlerParent(self.xmppclient) 412 plugin[1].setHandlerParent(current)
393 413
394 self.xmppclient.startService() 414 current.startService()
395 415
396 def disconnect(self): 416 def disconnect(self):
397 """disconnect from jabber server""" 417 """disconnect from jabber server"""
398 if (not self.isConnected()): 418 if (not self.isConnected()):
399 info("not connected !") 419 info("not connected !")
415 435
416 def stop(self): 436 def stop(self):
417 debug("stopping app") 437 debug("stopping app")
418 reactor.stop() 438 reactor.stop()
419 439
420 def streamInitialized(self):
421 """Called when xmlstream is OK"""
422 SatXMPPClient.streamInitialized(self.xmppclient)
423 debug ("XML stream is initialized")
424 self.xmlstream = self.xmppclient.xmlstream
425 self.me = self.xmppclient.jid #in case of the ressource has changed
426
427 self.disco = SatDiscoProtocol(self)
428 self.disco.setHandlerParent(self.xmppclient)
429 self.discoHandler = disco.DiscoHandler()
430 self.discoHandler.setHandlerParent(self.xmppclient)
431
432 self.roster.requestRoster()
433
434 self.presence.available()
435
436 self.disco.requestInfo(jid.JID(self.memory.getParamA("Server", "Connection"))).addCallback(self.serverDisco)
437
438 ## Misc methods ## 440 ## Misc methods ##
439 441
440 def registerNewAccount(self, login, password, server, port = 5222, id = None): 442 def registerNewAccount(self, login, password, server, port = 5222, id = None):
441 """Connect to a server and create a new account using in-band registration""" 443 """Connect to a server and create a new account using in-band registration"""
442 444
478 if accepted: 480 if accepted:
479 self.registerNewAccount(user, password, server, id=action_id) 481 self.registerNewAccount(user, password, server, id=action_id)
480 else: 482 else:
481 self.actionResult(action_id, "SUPPRESS", {}) 483 self.actionResult(action_id, "SUPPRESS", {})
482 484
483 def submitForm(self, action, target, fields): 485 def submitForm(self, action, target, fields, profile_key='@DEFAULT@'):
484 """submit a form 486 """submit a form
485 @param target: target jid where we are submitting 487 @param target: target jid where we are submitting
486 @param fields: list of tuples (name, value) 488 @param fields: list of tuples (name, value)
487 @return: tuple: (id, deferred) 489 @return: tuple: (id, deferred)
488 """ 490 """
491
492 profile = self.memory.getProfileName(profile_key)
493 assert(profile)
489 to_jid = jid.JID(target) 494 to_jid = jid.JID(target)
490 495
491 iq = compat.IQ(self.xmlstream, 'set') 496 iq = compat.IQ(self.profiles[profile].xmlstream, 'set')
492 iq["to"] = target 497 iq["to"] = target
493 iq["from"] = self.me.full() 498 iq["from"] = self.profiles[profile].jid.full()
494 query = iq.addElement(('jabber:iq:register', 'query')) 499 query = iq.addElement(('jabber:iq:register', 'query'))
495 if action=='SUBMIT': 500 if action=='SUBMIT':
496 form = XMLTools.tupleList2dataForm(fields) 501 form = XMLTools.tupleList2dataForm(fields)
497 query.addChild(form.toElement()) 502 query.addChild(form.toElement())
498 elif action=='CANCEL': 503 elif action=='CANCEL':
509 def setParam(self, name, value, category): 514 def setParam(self, name, value, category):
510 """set wanted paramater and notice observers""" 515 """set wanted paramater and notice observers"""
511 info ("setting param: %s=%s in category %s", name, value, category) 516 info ("setting param: %s=%s in category %s", name, value, category)
512 self.memory.setParam(name, value, category) 517 self.memory.setParam(name, value, category)
513 518
514 def failed(self,xmlstream): 519 def isConnected(self, profile_key='@DEFAULT@'):
515 debug("failed: %s", xmlstream.getErrorMessage()) 520 """Return connection status of profile
516 debug("failed: %s", dir(xmlstream)) 521 @param profile_key: key_word or profile name to determine profile name
517 522 @return True if connected
518 def isConnected(self): 523 """
519 try: 524 profile = self.memory.getProfileName(profile_key)
520 if self.xmppclient.isConnected(): 525 if not profile:
521 return True 526 error ('asking connection status for a non-existant profile')
522 except AttributeError: 527 raise Exception #TODO: raise a proper exception
523 #xmppclient not available 528 if not self.profiles.has_key(profile):
524 pass 529 return False
525 return False 530 return self.profiles[profile].isConnected()
526 531
527 def launchAction(self, type, data): 532 def launchAction(self, type, data):
528 """Launch a specific action asked by client 533 """Launch a specific action asked by client
529 @param type: action type (button) 534 @param type: action type (button)
530 @param data: needed data to launch the action 535 @param data: needed data to launch the action
545 return "" 550 return ""
546 551
547 552
548 ## jabber methods ## 553 ## jabber methods ##
549 554
550 def sendMessage(self,to,msg,type='chat'): 555 def sendMessage(self,to,msg,type='chat', profile_key='@DEFAULT@'):
551 #FIXME: check validity of recipient 556 #FIXME: check validity of recipient
557 profile = self.memory.getProfileName(profile_key)
558 assert(profile)
559 current_jid = self.profiles[profile].jid
552 debug("Sending jabber message to %s...", to) 560 debug("Sending jabber message to %s...", to)
553 message = domish.Element(('jabber:client','message')) 561 message = domish.Element(('jabber:client','message'))
554 message["to"] = jid.JID(to).full() 562 message["to"] = jid.JID(to).full()
555 message["from"] = self.me.full() 563 message["from"] = current_jid.full()
556 message["type"] = type 564 message["type"] = type
557 message.addElement("body", "jabber:client", msg) 565 message.addElement("body", "jabber:client", msg)
558 self.xmlstream.send(message) 566 self.profiles[profile].xmlstream.send(message)
559 self.memory.addToHistory(self.me, self.me, jid.JID(to), message["type"], unicode(msg)) 567 self.memory.addToHistory(current_jid, current_jid, jid.JID(to), message["type"], unicode(msg))
560 self.bridge.newMessage(message['from'], unicode(msg), to=message['to']) #We send back the message, so all clients are aware of it 568 self.bridge.newMessage(message['from'], unicode(msg), to=message['to']) #We send back the message, so all clients are aware of it
561 569
562 570
563 def setPresence(self, to="", show="", priority = 0, statuses={}): 571 def setPresence(self, to="", show="", priority = 0, statuses={}):
564 """Send our presence information""" 572 """Send our presence information"""