'Main procedure that performs XMPP stanza recognition and calling apppropriate handlers for it.
Called internally.'

def dispatch(self, stanza, session=None, direct=0):

    if (not session):
        session = self
    session.Stream._mini_dom = None
    name = stanza.getName()
    if ((not direct) and self._owner._route):
        if (name == 'route'):
            if (stanza.getAttr('error') == None):
                if (len(stanza.getChildren()) == 1):
                    stanza = stanza.getChildren()[0]
                    name = stanza.getName()
                else:
                    for each in stanza.getChildren():
                        self.dispatch(each, session, direct=1)
                    return
        elif (name == 'presence'):
            return
        elif (name in ('features', 'bind')):
            pass
        else:
            raise UnsupportedStanzaType(name)
    if (name == 'features'):
        session.Stream.features = stanza
    xmlns = stanza.getNamespace()
    if (not self.handlers.has_key(xmlns)):
        self.DEBUG(('Unknown    namespace:    ' + xmlns), 'warn')
        xmlns = 'unknown'
    if (not self.handlers[xmlns].has_key(name)):
        self.DEBUG(('Unknown    stanza:    ' + name), 'warn')
        name = 'unknown'
    else:
        self.DEBUG(('Got    %s/%s    stanza' % (xmlns, name)), 'ok')
    if (stanza.__class__.__name__ == 'Node'):
        stanza = self.handlers[xmlns][name][type](node=stanza)
    typ = stanza.getType()
    if (not typ):
        typ = ''
    stanza.props = stanza.getProperties()
    ID = stanza.getID()
    session.DEBUG(('Dispatching    %s    stanza    with    type->%s    props->%s    id->%s' % (name, typ, stanza.props, ID)), 'ok')
    list = ['default']
    if self.handlers[xmlns][name].has_key(typ):
        list.append(typ)
    for prop in stanza.props:
        if self.handlers[xmlns][name].has_key(prop):
            list.append(prop)
        if (typ and self.handlers[xmlns][name].has_key((typ + prop))):
            list.append((typ + prop))
    chain = self.handlers[xmlns]['default']['default']
    for key in list:
        if key:
            chain = (chain + self.handlers[xmlns][name][key])
    output = ''
    if session._expected.has_key(ID):
        user = 0
        if (type(session._expected[ID]) == type(())):
            (cb, args) = session._expected[ID]
            session.DEBUG(('Expected    stanza    arrived.    Callback    %s(%s)    found!' % (cb, args)), 'ok')
            try:
                cb(session, stanza, **args)
            except Exception as typ:
                if (typ.__class__.__name__ != 'NodeProcessed'):
                    raise
        else:
            session.DEBUG('Expected    stanza    arrived!', 'ok')
            session._expected[ID] = stanza
    else:
        user = 1
    for handler in chain:
        if (user or handler['system']):
            try:
                handler['func'](session, stanza)
            except Exception as typ:
                if (typ.__class__.__name__ != 'NodeProcessed'):
                    self._pendingExceptions.insert(0, sys.exc_info())
                    return
                user = 0
    if (user and self._defaultHandler):
        self._defaultHandler(session, stanza)
