modules/xmpp/dispatcher.py
author Mikael Berthe <mikael@lilotux.net>
Sat, 25 Aug 2007 15:46:55 +0200
changeset 42 cb52cef33d61
parent 0 93b25987d3e5
permissions -rw-r--r--
Update wtf DB
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     1
##   transports.py
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     2
##
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     3
##   Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     4
##
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     5
##   This program is free software; you can redistribute it and/or modify
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     6
##   it under the terms of the GNU General Public License as published by
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     7
##   the Free Software Foundation; either version 2, or (at your option)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     8
##   any later version.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     9
##
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    10
##   This program is distributed in the hope that it will be useful,
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    11
##   but WITHOUT ANY WARRANTY; without even the implied warranty of
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    12
##   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    13
##   GNU General Public License for more details.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    14
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    15
# $Id: dispatcher.py,v 1.41 2006/06/03 13:53:27 normanr Exp $
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    16
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    17
"""
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    18
Main xmpppy mechanism. Provides library with methods to assign different handlers
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    19
to different XMPP stanzas.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    20
Contains one tunable attribute: DefaultTimeout (25 seconds by default). It defines time that 
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    21
Dispatcher.SendAndWaitForResponce method will wait for reply stanza before giving up.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    22
"""
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    23
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    24
import simplexml,time,sys
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    25
from protocol import *
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    26
from client import PlugIn
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    27
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    28
DefaultTimeout=25
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    29
ID=0
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    30
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    31
class Dispatcher(PlugIn):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    32
    """ Ancestor of PlugIn class. Handles XMPP stream, i.e. aware of stream headers.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    33
        Can be plugged out/in to restart these headers (used for SASL f.e.). """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    34
    def __init__(self):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    35
        PlugIn.__init__(self)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    36
        DBG_LINE='dispatcher'
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    37
        self.handlers={}
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    38
        self._expected={}
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    39
        self._defaultHandler=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    40
        self._pendingExceptions=[]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    41
        self._eventHandler=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    42
        self._cycleHandlers=[]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    43
        self._exported_methods=[self.Process,self.RegisterHandler,self.RegisterDefaultHandler,\
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    44
        self.RegisterEventHandler,self.UnregisterCycleHandler,self.RegisterCycleHandler,\
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    45
        self.RegisterHandlerOnce,self.UnregisterHandler,self.RegisterProtocol,\
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    46
        self.WaitForResponse,self.SendAndWaitForResponse,self.send,self.disconnect,\
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    47
        self.SendAndCallForResponse, ]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    48
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    49
    def dumpHandlers(self):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    50
        """ Return set of user-registered callbacks in it's internal format.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    51
            Used within the library to carry user handlers set over Dispatcher replugins. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    52
        return self.handlers
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    53
    def restoreHandlers(self,handlers):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    54
        """ Restores user-registered callbacks structure from dump previously obtained via dumpHandlers.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    55
            Used within the library to carry user handlers set over Dispatcher replugins. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    56
        self.handlers=handlers
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    57
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    58
    def _init(self):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    59
        """ Registers default namespaces/protocols/handlers. Used internally.  """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    60
        self.RegisterNamespace('unknown')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    61
        self.RegisterNamespace(NS_STREAMS)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    62
        self.RegisterNamespace(self._owner.defaultNamespace)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    63
        self.RegisterProtocol('iq',Iq)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    64
        self.RegisterProtocol('presence',Presence)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    65
        self.RegisterProtocol('message',Message)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    66
        self.RegisterDefaultHandler(self.returnStanzaHandler)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    67
        self.RegisterHandler('error',self.streamErrorHandler,xmlns=NS_STREAMS)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    68
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    69
    def plugin(self, owner):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    70
        """ Plug the Dispatcher instance into Client class instance and send initial stream header. Used internally."""
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    71
        self._init()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    72
        for method in self._old_owners_methods:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    73
            if method.__name__=='send': self._owner_send=method; break
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    74
        self._owner.lastErrNode=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    75
        self._owner.lastErr=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    76
        self._owner.lastErrCode=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    77
        self.StreamInit()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    78
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    79
    def plugout(self):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    80
        """ Prepares instance to be destructed. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    81
        self.Stream.dispatch=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    82
        self.Stream.DEBUG=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    83
        self.Stream.features=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    84
        self.Stream.destroy()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    85
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    86
    def StreamInit(self):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    87
        """ Send an initial stream header. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    88
        self.Stream=simplexml.NodeBuilder()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    89
        self.Stream._dispatch_depth=2
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    90
        self.Stream.dispatch=self.dispatch
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    91
        self.Stream.stream_header_received=self._check_stream_start
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    92
        self._owner.debug_flags.append(simplexml.DBG_NODEBUILDER)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    93
        self.Stream.DEBUG=self._owner.DEBUG
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    94
        self.Stream.features=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    95
        self._metastream=Node('stream:stream')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    96
        self._metastream.setNamespace(self._owner.Namespace)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    97
        self._metastream.setAttr('version','1.0')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    98
        self._metastream.setAttr('xmlns:stream',NS_STREAMS)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    99
        self._metastream.setAttr('to',self._owner.Server)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   100
        self._owner.send("<?xml version='1.0'?>%s>"%str(self._metastream)[:-2])
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   101
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   102
    def _check_stream_start(self,ns,tag,attrs):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   103
        if ns<>NS_STREAMS or tag<>'stream':
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   104
            raise ValueError('Incorrect stream start: (%s,%s). Terminating.'%(tag,ns))
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   105
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   106
    def Process(self, timeout=0):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   107
        """ Check incoming stream for data waiting. If "timeout" is positive - block for as max. this time.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   108
            Returns:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   109
            1) length of processed data if some data were processed;
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   110
            2) '0' string if no data were processed but link is alive;
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   111
            3) 0 (zero) if underlying connection is closed.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   112
            Take note that in case of disconnection detect during Process() call
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   113
            disconnect handlers are called automatically.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   114
        """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   115
        for handler in self._cycleHandlers: handler(self)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   116
        if len(self._pendingExceptions) > 0:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   117
            _pendingException = self._pendingExceptions.pop()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   118
            raise _pendingException[0], _pendingException[1], _pendingException[2]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   119
        if self._owner.Connection.pending_data(timeout):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   120
            try: data=self._owner.Connection.receive()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   121
            except IOError: return
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   122
            self.Stream.Parse(data)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   123
            if len(self._pendingExceptions) > 0:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   124
                _pendingException = self._pendingExceptions.pop()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   125
                raise _pendingException[0], _pendingException[1], _pendingException[2]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   126
            if data: return len(data)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   127
        return '0'      # It means that nothing is received but link is alive.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   128
        
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   129
    def RegisterNamespace(self,xmlns,order='info'):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   130
        """ Creates internal structures for newly registered namespace.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   131
            You can register handlers for this namespace afterwards. By default one namespace
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   132
            already registered (jabber:client or jabber:component:accept depending on context. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   133
        self.DEBUG('Registering namespace "%s"'%xmlns,order)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   134
        self.handlers[xmlns]={}
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   135
        self.RegisterProtocol('unknown',Protocol,xmlns=xmlns)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   136
        self.RegisterProtocol('default',Protocol,xmlns=xmlns)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   137
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   138
    def RegisterProtocol(self,tag_name,Proto,xmlns=None,order='info'):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   139
        """ Used to declare some top-level stanza name to dispatcher.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   140
           Needed to start registering handlers for such stanzas.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   141
           Iq, message and presence protocols are registered by default. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   142
        if not xmlns: xmlns=self._owner.defaultNamespace
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   143
        self.DEBUG('Registering protocol "%s" as %s(%s)'%(tag_name,Proto,xmlns), order)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   144
        self.handlers[xmlns][tag_name]={type:Proto, 'default':[]}
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   145
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   146
    def RegisterNamespaceHandler(self,xmlns,handler,typ='',ns='', makefirst=0, system=0):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   147
        """ Register handler for processing all stanzas for specified namespace. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   148
        self.RegisterHandler('default', handler, typ, ns, xmlns, makefirst, system)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   149
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   150
    def RegisterHandler(self,name,handler,typ='',ns='',xmlns=None, makefirst=0, system=0):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   151
        """Register user callback as stanzas handler of declared type. Callback must take
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   152
           (if chained, see later) arguments: dispatcher instance (for replying), incomed
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   153
           return of previous handlers.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   154
           The callback must raise xmpp.NodeProcessed just before return if it want preven
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   155
           callbacks to be called with the same stanza as argument _and_, more importantly
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   156
           library from returning stanza to sender with error set (to be enabled in 0.2 ve
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   157
            Arguments:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   158
              "name" - name of stanza. F.e. "iq".
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   159
              "handler" - user callback.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   160
              "typ" - value of stanza's "type" attribute. If not specified any value match
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   161
              "ns" - namespace of child that stanza must contain.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   162
              "chained" - chain together output of several handlers.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   163
              "makefirst" - insert handler in the beginning of handlers list instead of
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   164
                adding it to the end. Note that more common handlers (i.e. w/o "typ" and "
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   165
                will be called first nevertheless.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   166
              "system" - call handler even if NodeProcessed Exception were raised already.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   167
            """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   168
        if not xmlns: xmlns=self._owner.defaultNamespace
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   169
        self.DEBUG('Registering handler %s for "%s" type->%s ns->%s(%s)'%(handler,name,typ,ns,xmlns), 'info')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   170
        if not typ and not ns: typ='default'
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   171
        if not self.handlers.has_key(xmlns): self.RegisterNamespace(xmlns,'warn')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   172
        if not self.handlers[xmlns].has_key(name): self.RegisterProtocol(name,Protocol,xmlns,'warn')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   173
        if not self.handlers[xmlns][name].has_key(typ+ns): self.handlers[xmlns][name][typ+ns]=[]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   174
        if makefirst: self.handlers[xmlns][name][typ+ns].insert(0,{'func':handler,'system':system})
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   175
        else: self.handlers[xmlns][name][typ+ns].append({'func':handler,'system':system})
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   176
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   177
    def RegisterHandlerOnce(self,name,handler,typ='',ns='',xmlns=None,makefirst=0, system=0):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   178
        """ Unregister handler after first call (not implemented yet). """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   179
        if not xmlns: xmlns=self._owner.defaultNamespace
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   180
        self.RegisterHandler(name, handler, typ, ns, xmlns, makefirst, system)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   181
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   182
    def UnregisterHandler(self,name,handler,typ='',ns='',xmlns=None):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   183
        """ Unregister handler. "typ" and "ns" must be specified exactly the same as with registering."""
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   184
        if not xmlns: xmlns=self._owner.defaultNamespace
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   185
        if not typ and not ns: typ='default'
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   186
        for pack in self.handlers[xmlns][name][typ+ns]:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   187
            if handler==pack['func']: break
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   188
        else: pack=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   189
        try: self.handlers[xmlns][name][typ+ns].remove(pack)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   190
        except ValueError: pass
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   191
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   192
    def RegisterDefaultHandler(self,handler):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   193
        """ Specify the handler that will be used if no NodeProcessed exception were raised.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   194
            This is returnStanzaHandler by default. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   195
        self._defaultHandler=handler
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   196
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   197
    def RegisterEventHandler(self,handler):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   198
        """ Register handler that will process events. F.e. "FILERECEIVED" event. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   199
        self._eventHandler=handler
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   200
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   201
    def returnStanzaHandler(self,conn,stanza):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   202
        """ Return stanza back to the sender with <feature-not-implemennted/> error set. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   203
        if stanza.getType() in ['get','set']:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   204
            conn.send(Error(stanza,ERR_FEATURE_NOT_IMPLEMENTED))
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   205
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   206
    def streamErrorHandler(self,conn,error):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   207
        name,text='error',error.getData()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   208
        for tag in error.getChildren():
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   209
            if tag.getNamespace()==NS_XMPP_STREAMS:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   210
                if tag.getName()=='text': text=tag.getData()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   211
                else: name=tag.getName()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   212
        if name in stream_exceptions.keys(): exc=stream_exceptions[name]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   213
        else: exc=StreamError
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   214
        raise exc((name,text))
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   215
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   216
    def RegisterCycleHandler(self,handler):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   217
        """ Register handler that will be called on every Dispatcher.Process() call. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   218
        if handler not in self._cycleHandlers: self._cycleHandlers.append(handler)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   219
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   220
    def UnregisterCycleHandler(self,handler):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   221
        """ Unregister handler that will is called on every Dispatcher.Process() call."""
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   222
        if handler in self._cycleHandlers: self._cycleHandlers.remove(handler)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   223
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   224
    def Event(self,realm,event,data):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   225
        """ Raise some event. Takes three arguments:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   226
            1) "realm" - scope of event. Usually a namespace. 
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   227
            2) "event" - the event itself. F.e. "SUCESSFULL SEND".
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   228
            3) data that comes along with event. Depends on event."""
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   229
        if self._eventHandler: self._eventHandler(realm,event,data)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   230
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   231
    def dispatch(self,stanza,session=None,direct=0):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   232
        """ Main procedure that performs XMPP stanza recognition and calling apppropriate handlers for it.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   233
            Called internally. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   234
        if not session: session=self
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   235
        session.Stream._mini_dom=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   236
        name=stanza.getName()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   237
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   238
        if not direct and self._owner._route:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   239
            if name == 'route':
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   240
                if stanza.getAttr('error') == None:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   241
                    if len(stanza.getChildren()) == 1:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   242
                        stanza = stanza.getChildren()[0]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   243
                        name=stanza.getName()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   244
                    else:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   245
                        for each in stanza.getChildren():
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   246
                            self.dispatch(each,session,direct=1)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   247
                        return
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   248
            elif name == 'presence':
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   249
                return
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   250
            elif name in ('features','bind'):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   251
                pass
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   252
            else:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   253
                raise UnsupportedStanzaType(name)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   254
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   255
        if name=='features': session.Stream.features=stanza
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   256
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   257
        xmlns=stanza.getNamespace()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   258
        if not self.handlers.has_key(xmlns):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   259
            self.DEBUG("Unknown namespace: " + xmlns,'warn')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   260
            xmlns='unknown'
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   261
        if not self.handlers[xmlns].has_key(name):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   262
            self.DEBUG("Unknown stanza: " + name,'warn')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   263
            name='unknown'
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   264
        else:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   265
            self.DEBUG("Got %s/%s stanza"%(xmlns,name), 'ok')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   266
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   267
        if stanza.__class__.__name__=='Node': stanza=self.handlers[xmlns][name][type](node=stanza)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   268
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   269
        typ=stanza.getType()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   270
        if not typ: typ=''
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   271
        stanza.props=stanza.getProperties()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   272
        ID=stanza.getID()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   273
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   274
        session.DEBUG("Dispatching %s stanza with type->%s props->%s id->%s"%(name,typ,stanza.props,ID),'ok')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   275
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   276
        list=['default']                                                     # we will use all handlers:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   277
        if self.handlers[xmlns][name].has_key(typ): list.append(typ)                # from very common...
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   278
        for prop in stanza.props:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   279
            if self.handlers[xmlns][name].has_key(prop): list.append(prop)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   280
            if typ and self.handlers[xmlns][name].has_key(typ+prop): list.append(typ+prop)  # ...to very particular
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   281
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   282
        chain=self.handlers[xmlns]['default']['default']
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   283
        for key in list:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   284
            if key: chain = chain + self.handlers[xmlns][name][key]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   285
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   286
        output=''
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   287
        if session._expected.has_key(ID):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   288
            user=0
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   289
            if type(session._expected[ID])==type(()):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   290
                cb,args=session._expected[ID]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   291
                session.DEBUG("Expected stanza arrived. Callback %s(%s) found!"%(cb,args),'ok')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   292
                try: cb(session,stanza,**args)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   293
                except Exception, typ:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   294
                    if typ.__class__.__name__<>'NodeProcessed': raise
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   295
            else:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   296
                session.DEBUG("Expected stanza arrived!",'ok')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   297
                session._expected[ID]=stanza
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   298
        else: user=1
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   299
        for handler in chain:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   300
            if user or handler['system']:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   301
                try:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   302
                    handler['func'](session,stanza)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   303
                except Exception, typ:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   304
                    if typ.__class__.__name__<>'NodeProcessed':
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   305
                        self._pendingExceptions.insert(0, sys.exc_info())
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   306
                        return
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   307
                    user=0
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   308
        if user and self._defaultHandler: self._defaultHandler(session,stanza)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   309
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   310
    def WaitForResponse(self, ID, timeout=DefaultTimeout):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   311
        """ Block and wait until stanza with specific "id" attribute will come.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   312
            If no such stanza is arrived within timeout, return None.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   313
            If operation failed for some reason then owner's attributes
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   314
            lastErrNode, lastErr and lastErrCode are set accordingly. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   315
        self._expected[ID]=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   316
        has_timed_out=0
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   317
        abort_time=time.time() + timeout
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   318
        self.DEBUG("Waiting for ID:%s with timeout %s..." % (ID,timeout),'wait')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   319
        while not self._expected[ID]:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   320
            if not self.Process(0.04):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   321
                self._owner.lastErr="Disconnect"
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   322
                return None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   323
            if time.time() > abort_time:
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   324
                self._owner.lastErr="Timeout"
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   325
                return None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   326
        response=self._expected[ID]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   327
        del self._expected[ID]
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   328
        if response.getErrorCode():
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   329
            self._owner.lastErrNode=response
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   330
            self._owner.lastErr=response.getError()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   331
            self._owner.lastErrCode=response.getErrorCode()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   332
        return response
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   333
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   334
    def SendAndWaitForResponse(self, stanza, timeout=DefaultTimeout):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   335
        """ Put stanza on the wire and wait for recipient's response to it. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   336
        return self.WaitForResponse(self.send(stanza),timeout)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   337
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   338
    def SendAndCallForResponse(self, stanza, func, args={}):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   339
        """ Put stanza on the wire and call back when recipient replies.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   340
            Additional callback arguments can be specified in args. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   341
        self._expected[self.send(stanza)]=(func,args)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   342
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   343
    def send(self,stanza):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   344
        """ Serialise stanza and put it on the wire. Assign an unique ID to it before send.
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   345
            Returns assigned ID."""
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   346
        if type(stanza) in [type(''), type(u'')]: return self._owner_send(stanza)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   347
        if not isinstance(stanza,Protocol): _ID=None
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   348
        elif not stanza.getID():
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   349
            global ID
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   350
            ID+=1
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   351
            _ID=`ID`
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   352
            stanza.setID(_ID)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   353
        else: _ID=stanza.getID()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   354
        if self._owner._registered_name and not stanza.getAttr('from'): stanza.setAttr('from',self._owner._registered_name)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   355
        if self._owner._route and stanza.getName()!='bind':
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   356
            to=self._owner.Server
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   357
            if stanza.getTo() and stanza.getTo().getDomain():
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   358
                to=stanza.getTo().getDomain()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   359
            frm=stanza.getFrom()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   360
            if frm.getDomain():
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   361
                frm=frm.getDomain()
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   362
            route=Protocol('route',to=to,frm=frm,payload=[stanza])
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   363
            stanza=route
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   364
        stanza.setNamespace(self._owner.Namespace)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   365
        stanza.setParent(self._metastream)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   366
        self._owner_send(stanza)
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   367
        return _ID
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   368
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   369
    def disconnect(self):
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   370
        """ Send a stream terminator and and handle all incoming stanzas before stream closure. """
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   371
        self._owner_send('</stream:stream>')
93b25987d3e5 Initial Mercurial repository
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   372
        while self.Process(1): pass