Changeset 658
- Timestamp:
- 05/11/08 12:39:06 (7 months ago)
- Files:
-
- oss/headstock/headstock/api/contact.py (modified) (5 diffs)
- oss/headstock/headstock/example/simplechat/simplechat.py (modified) (9 diffs)
- oss/headstock/headstock/protocol/core/presence.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
oss/headstock/headstock/api/contact.py
r654 r658 15 15 16 16 class Presence(Entity): 17 def __init__(self, from_jid, to_jid=None ):18 Entity.__init__(self, from_jid, to_jid )17 def __init__(self, from_jid, to_jid=None, type=u'none', stanza_id=None): 18 Entity.__init__(self, from_jid, to_jid, type=type, stanza_id=stanza_id) 19 19 self.status = None 20 20 self.show = None 21 21 self.priority = 0 22 self.subscription = u'none'23 22 self.foreign = [] 24 23 … … 29 28 def from_element(e): 30 29 p = Presence(JID.parse(e.get_attribute_value('from')), 31 JID.parse(e.get_attribute_value('to')) )32 p.subscription = e.get_attribute_value('type', None)30 JID.parse(e.get_attribute_value('to')), 31 e.get_attribute_value('type', None)) 33 32 34 33 for child in e.xml_children: … … 52 51 if p.to_jid: 53 52 attrs[u'to'] = unicode(p.to_jid) 54 if p. subscription:55 attrs[u'type'] = p. subscription53 if p.type: 54 attrs[u'type'] = p.type 56 55 e = E(u'presence', attributes=attrs, namespace=XMPP_CLIENT_NS) 57 56 … … 85 84 86 85 class Roster(Entity): 87 def __init__(self, from_jid, to_jid ):88 Entity.__init__(self, from_jid, to_jid )86 def __init__(self, from_jid, to_jid=None, type=u'get', stanza_id=None): 87 Entity.__init__(self, from_jid, to_jid, type=type, stanza_id=stanza_id) 89 88 self.items = {} 90 89 … … 109 108 110 109 return r 110 111 @staticmethod 112 def to_element(e): 113 iq = Entity.to_element(e) 114 if e.type != 'result': 115 query = E(u'query', namespace=XMPP_ROSTER_NS, parent=iq) 116 for item_id in e.items: 117 item = e.items[item_id] 118 attr = {u'jid': unicode(item.jid)} 119 if item.subscription: 120 attr[u'subscription'] = item.subscription 121 if item.name: 122 attr[u'name'] = item.name 123 if item.language: 124 attr[u'language'] = item.language 125 i = E(u'item', namespace=XMPP_ROSTER_NS, 126 attributes=attr, parent=query) 127 for group in item.groups: 128 E(u'group', namespace=XMPP_ROSTER_NS, 129 content=group, parent=i) 130 return iq 131 oss/headstock/headstock/example/simplechat/simplechat.py
r657 r658 35 35 36 36 from headstock.protocol.core.stream import ClientStream, StreamError, SaslError 37 from headstock.protocol.core.presence import PresenceDispatcher , PresenceSubscriber37 from headstock.protocol.core.presence import PresenceDispatcher 38 38 from headstock.protocol.core.roster import RosterDispatcher, RosterNull 39 39 from headstock.protocol.core.message import MessageDispatcher, MessageEchoer … … 45 45 from headstock.lib.logger import Logger 46 46 from headstock.api.im import Message, Body, Event 47 from headstock.api.contact import Presence 47 from headstock.api.contact import Presence, Roster, Item 48 from headstock.api import Entity 48 49 from headstock.api.activity import Activity 49 50 from headstock.lib.utils import generate_unique … … 58 59 Inboxes = {"inbox" : "headstock.api.contact.Roster instance", 59 60 "control" : "stops the component", 61 "pushed" : "roster stanzas pushed by the server", 60 62 "jid" : "headstock.api.jid.JID instance received from the server", 61 63 "ask-activity" : "request activity status to the server for each roster contact"} … … 64 66 "signal" : "Shutdown signal", 65 67 "message" : "Message to send", 68 "result" : "", 66 69 "activity" : "headstock.api.activity.Activity instance to send to the server"} 67 70 … … 96 99 self.from_jid = self.recv('jid') 97 100 101 if self.dataReady("pushed"): 102 roster = self.recv('pushed') 103 for nodeid in roster.items: 104 self.send(Roster(from_jid=self.from_jid, to_jid=nodeid, 105 type=u'result', stanza_id=generate_unique()), 'result') 106 98 107 if self.dataReady("inbox"): 99 108 roster = self.recv("inbox") … … 309 318 yield 1 310 319 320 class PresenceHandler(component): 321 Inboxes = {"inbox" : "headstock.api.contact.Presence instance", 322 "control" : "Shutdown the client stream", 323 "subscribe" : "", 324 "unsubscribe" : "",} 325 326 Outboxes = {"outbox" : "headstock.api.contact.Presence instance to return to the server", 327 "signal" : "Shutdown signal", 328 "roster" : "", 329 "log" : "log",} 330 331 def __init__(self): 332 super(PresenceHandler, self).__init__() 333 334 def main(self): 335 while 1: 336 if self.dataReady("control"): 337 mes = self.recv("control") 338 339 if isinstance(mes, shutdownMicroprocess) or isinstance(mes, producerFinished): 340 self.send(producerFinished(), "signal") 341 break 342 343 if self.dataReady("subscribe"): 344 p = self.recv("subscribe") 345 p.swap_jids() 346 347 # Automatically accept any subscription requests 348 p = Presence(from_jid=p.from_jid, to_jid=unicode(p.to_jid), 349 type=u'subscribed') 350 self.send(p, "outbox") 351 352 # Automatically subscribe in return as well 353 p = Presence(from_jid=p.from_jid, to_jid=unicode(p.to_jid), 354 type=u'subscribe') 355 self.send(p, "outbox") 356 357 if self.dataReady("unsubscribe"): 358 p = self.recv("unsubscribe") 359 p.swap_jids() 360 361 # We stop our subscription to the other user 362 p = Presence(from_jid=p.from_jid, to_jid=unicode(p.to_jid), 363 type=u'unsubscribed') 364 self.send(p, "outbox") 365 366 # We stop the other user's subscription 367 p = Presence(from_jid=p.from_jid, to_jid=unicode(p.to_jid), 368 type=u'unsubscribe') 369 self.send(p, "outbox") 370 371 # We remove this user from our roster list 372 r = Roster(from_jid=p.from_jid, type=u'set') 373 i = Item(p.to_jid) 374 i.subscription = u'remove' 375 r.items[unicode(p.to_jid)] = i 376 self.send(r, 'roster') 377 378 # We tell the other user we're not available anymore 379 p = Presence(from_jid=p.from_jid, to_jid=unicode(p.to_jid), 380 type=u'unavailable') 381 self.send(p, "outbox") 382 383 if not self.anyReady(): 384 self.pause() 385 386 yield 1 387 388 311 389 class Client(component): 312 390 Inboxes = {"inbox" : "", … … 336 414 return self.password 337 415 338 def subscription_requested(self, p):339 # If you don't accept the subscription request, simply return None340 # otherwise returns "p"341 342 # Note that you could for instance call your database, or ask the343 # user, etc.344 print "# %s wants to subscribe to you. Enter 'yes' to allow, 'no' otherwise" % str(p.from_jid)345 allow = raw_input(">>> ")346 if allow == 'yes':347 p.swap_jids()348 return p349 350 416 def shutdown(self): 351 p = Presence(self.jid) 352 p.subscription = u'unavailable' 353 self.send(Presence.to_element(p), 'forward') 417 self.send(Presence.to_element(Presence(self.jid, type=u'unavailable')), 'forward') 354 418 self.send('OUTGOING : </stream:stream>', 'log') 355 419 self.send('</stream:stream>', 'outbox') … … 408 472 rosterhandler = RosterHandler(self.jid), 409 473 msgdummyhandler = DummyMessageHandler(), 474 presencehandler = PresenceHandler(), 410 475 presencedisp = PresenceDispatcher(), 411 presencesub = PresenceSubscriber(self.subscription_requested),412 476 rosterdisp = RosterDispatcher(), 413 477 msgdisp = MessageDispatcher(), … … 436 500 ("xmpp", "%s.presence" % XMPP_CLIENT_NS): ("presencedisp", "inbox"), 437 501 ("presencedisp", "log"): ('logger', "inbox"), 438 ("presencedisp", "xmpp.subscribe"): ("presencesub", "inbox"), 439 ("presencesub", "outbox"): ("xmpp", "forward"), 502 ("presencedisp", "xmpp.subscribe"): ("presencehandler", "subscribe"), 503 ("presencedisp", "xmpp.unsubscribe"): ("presencehandler", "unsubscribe"), 504 ("presencehandler", "outbox"): ("presencedisp", "forward"), 505 ("presencehandler", "roster"): ("rosterdisp", "forward"), 506 ("presencedisp", "outbox"): ("xmpp", "forward"), 440 507 441 508 # Roster 442 509 ("xmpp", "%s.query" % XMPP_ROSTER_NS): ("rosterdisp", "inbox"), 443 510 ("rosterdisp", "log"): ('logger', "inbox"), 511 ('rosterdisp', 'xmpp.set'): ('rosterhandler', 'pushed'), 444 512 ('rosterdisp', 'xmpp.result'): ('rosterhandler', 'inbox'), 513 ('rosterhandler', 'result'): ('rosterdisp', 'forward'), 514 ("rosterdisp", "outbox"): ("xmpp", "forward"), 445 515 446 516 # Discovery oss/headstock/headstock/protocol/core/presence.py
r652 r658 12 12 from bridge.common import XMPP_CLIENT_NS 13 13 14 __all__ = ['PresenceDispatcher' , 'PresenceSubscriber']14 __all__ = ['PresenceDispatcher'] 15 15 16 # Helper function17 def create_presence(from_jid=None, to_jid=None, presence_type=None, status=None, show=None):18 stanza = Stanza(u'presence', from_jid, to_jid, presence_type)19 if status:20 E(u'status', content=status, namespace=stanza.xml_ns, parent=stanza)21 if show:22 E(u'show', content=show, namespace=stanza.xml_ns, parent=stanza)23 24 return stanza.to_element()25 26 16 class PresenceDispatcher(component): 27 17 Inboxes = {"inbox" : "bridge.Element instance", 28 "control" : " Shutdown the client stream",18 "control" : "stops the component", 29 19 "forward" : "headstock.api.contact.Presence instance to be sent back to the client. Transforms the instance to a bridge.Element instance and puts it into the 'outbox'", 30 20 } … … 34 24 "log" : "log", 35 25 "unknown" : "Unknown element that could not be dispatched properly", 26 "xmpp.unavailable" : "Notifiy an entity of one's availability", 36 27 "xmpp.error" : "An error has occurred regarding processing or delivery of a presence stanza", 37 28 "xmpp.probe" : "Server to server message to check the presence of an entity", … … 78 69 79 70 yield 1 80 81 class PresenceSubscriber(component):82 Inboxes = {"inbox" : "headstock.api.contact.Presence instance",83 "control" : "Shutdown the client stream",84 }85 86 Outboxes = {"outbox" : "bridge.Element instance to sent back to the client",87 "signal" : "Shutdown signal",88 }89 90 def __init__(self, subscribe_cb):91 """92 Component that handles passing the message to the server that a subscribtion93 was either allowed or refused.94 95 The ``subscribe_cb`` must be a callable that takes a headstock.api.contact.Presence instance96 and returns either that instance to allow the subscription or None to reject it.97 """98 super(PresenceSubscriber, self).__init__()99 self.subscribe_cb = subscribe_cb100 101 def main(self):102 while 1:103 if self.dataReady("control"):104 mes = self.recv("control")105 106 if isinstance(mes, shutdownMicroprocess) or isinstance(mes, producerFinished):107 self.send(producerFinished(), "signal")108 break109 110 if self.dataReady("inbox"):111 p = self.recv("inbox")112 113 action = self.subscribe_cb(p)114 if action == None:115 e = create_presence(to_jid=unicode(p.to_jid),116 presence_type=u'unsubscribed')117 else:118 # action is now the new instance of 'p' and may have been119 # modified by the callback function120 e = create_presence(to_jid=unicode(action.to_jid),121 presence_type=u'subscribed')122 123 self.send(e, "outbox")124 125 if not self.anyReady():126 self.pause()127 128 yield 1129 130 131 class PresenceUnsubscriber(component):132 Inboxes = {"inbox" : "bridge.Element instance",133 "control" : "Shutdown the client stream",134 }135 136 Outboxes = {"outbox" : "bridge.Element instance to sent back to the client",137 "signal" : "Shutdown signal",138 "log" : "log",139 }140 141 def __init__(self):142 super(PresenceUnsubscriber, self).__init__()143 144 def main(self):145 while 1:146 if self.dataReady("control"):147 mes = self.recv("control")148 149 if isinstance(mes, shutdownMicroprocess) or isinstance(mes, producerFinished):150 self.send(producerFinished(), "signal")151 break152 153 if self.dataReady("inbox"):154 e = self.recv("inbox")155 156 if not self.anyReady():157 self.pause()158 159 yield 1160
