Smacks class added, responds to ack requests
This commit is contained in:
parent
9cf9de2a14
commit
5b1edd03b8
4 changed files with 76 additions and 8 deletions
|
@ -21,7 +21,7 @@ Can be used both for client and transport authentication
|
||||||
See client_nb.py
|
See client_nb.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from protocol import NS_SASL, NS_SESSION, NS_STREAMS, NS_BIND, NS_AUTH
|
from protocol import NS_SASL, NS_SESSION, NS_STREAMS, NS_BIND, NS_AUTH, NS_STREAM_MGMT
|
||||||
from protocol import Node, NodeProcessed, isResultNode, Iq, Protocol, JID
|
from protocol import Node, NodeProcessed, isResultNode, Iq, Protocol, JID
|
||||||
from plugin import PlugIn
|
from plugin import PlugIn
|
||||||
import base64
|
import base64
|
||||||
|
@ -31,7 +31,7 @@ import dispatcher_nb
|
||||||
import hashlib
|
import hashlib
|
||||||
import hmac
|
import hmac
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from smacks import Smacks
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger('gajim.c.x.auth_nb')
|
log = logging.getLogger('gajim.c.x.auth_nb')
|
||||||
|
|
||||||
|
@ -491,7 +491,8 @@ class NonBlockingNonSASL(PlugIn):
|
||||||
self.password = password
|
self.password = password
|
||||||
self.resource = resource
|
self.resource = resource
|
||||||
self.on_auth = on_auth
|
self.on_auth = on_auth
|
||||||
|
|
||||||
|
|
||||||
def plugin(self, owner):
|
def plugin(self, owner):
|
||||||
"""
|
"""
|
||||||
Determine the best auth method (digest/0k/plain) and use it for auth.
|
Determine the best auth method (digest/0k/plain) and use it for auth.
|
||||||
|
@ -564,6 +565,7 @@ class NonBlockingBind(PlugIn):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
PlugIn.__init__(self)
|
PlugIn.__init__(self)
|
||||||
self.bound = None
|
self.bound = None
|
||||||
|
self.supports_sm = False
|
||||||
|
|
||||||
def plugin(self, owner):
|
def plugin(self, owner):
|
||||||
''' Start resource binding, if allowed at this time. Used internally. '''
|
''' Start resource binding, if allowed at this time. Used internally. '''
|
||||||
|
@ -580,8 +582,14 @@ class NonBlockingBind(PlugIn):
|
||||||
def FeaturesHandler(self, conn, feats):
|
def FeaturesHandler(self, conn, feats):
|
||||||
"""
|
"""
|
||||||
Determine if server supports resource binding and set some internal
|
Determine if server supports resource binding and set some internal
|
||||||
attributes accordingly
|
attributes accordingly.
|
||||||
|
|
||||||
|
It also checks if server supports stream management
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if feats.getTag('sm', namespace=NS_STREAM_MGMT):
|
||||||
|
self.supports_sm = True # server supports stream management
|
||||||
|
|
||||||
if not feats.getTag('bind', namespace=NS_BIND):
|
if not feats.getTag('bind', namespace=NS_BIND):
|
||||||
log.info('Server does not requested binding.')
|
log.info('Server does not requested binding.')
|
||||||
# we try to bind resource anyway
|
# we try to bind resource anyway
|
||||||
|
@ -625,6 +633,14 @@ class NonBlockingBind(PlugIn):
|
||||||
jid = JID(resp.getTag('bind').getTagData('jid'))
|
jid = JID(resp.getTag('bind').getTagData('jid'))
|
||||||
self._owner.User = jid.getNode()
|
self._owner.User = jid.getNode()
|
||||||
self._owner.Resource = jid.getResource()
|
self._owner.Resource = jid.getResource()
|
||||||
|
# Only negociate stream management after bounded
|
||||||
|
if self.supports_sm:
|
||||||
|
# starts negociation
|
||||||
|
sm = Smacks(self._owner)
|
||||||
|
self._owner.Dispatcher.supports_sm = True
|
||||||
|
self._owner.Dispatcher.sm = sm
|
||||||
|
sm.negociate()
|
||||||
|
|
||||||
if hasattr(self, 'session') and self.session == -1:
|
if hasattr(self, 'session') and self.session == -1:
|
||||||
# Server don't want us to initialize a session
|
# Server don't want us to initialize a session
|
||||||
log.info('No session required.')
|
log.info('No session required.')
|
||||||
|
|
|
@ -75,7 +75,7 @@ class XMPPDispatcher(PlugIn):
|
||||||
stream headers (used by SASL f.e.).
|
stream headers (used by SASL f.e.).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
PlugIn.__init__(self)
|
PlugIn.__init__(self)
|
||||||
self.handlers = {}
|
self.handlers = {}
|
||||||
self._expected = {}
|
self._expected = {}
|
||||||
|
@ -89,6 +89,9 @@ class XMPPDispatcher(PlugIn):
|
||||||
self.UnregisterHandler, self.RegisterProtocol,
|
self.UnregisterHandler, self.RegisterProtocol,
|
||||||
self.SendAndWaitForResponse, self.SendAndCallForResponse,
|
self.SendAndWaitForResponse, self.SendAndCallForResponse,
|
||||||
self.getAnID, self.Event, self.send]
|
self.getAnID, self.Event, self.send]
|
||||||
|
|
||||||
|
# Let the dispatcher know if there is support for stream management
|
||||||
|
self.supports_sm = False
|
||||||
|
|
||||||
def getAnID(self):
|
def getAnID(self):
|
||||||
global outgoingID
|
global outgoingID
|
||||||
|
@ -110,6 +113,7 @@ class XMPPDispatcher(PlugIn):
|
||||||
"""
|
"""
|
||||||
self.handlers = handlers
|
self.handlers = handlers
|
||||||
|
|
||||||
|
|
||||||
def _init(self):
|
def _init(self):
|
||||||
"""
|
"""
|
||||||
Register default namespaces/protocols/handlers. Used internally
|
Register default namespaces/protocols/handlers. Used internally
|
||||||
|
@ -125,7 +129,7 @@ class XMPPDispatcher(PlugIn):
|
||||||
self.RegisterDefaultHandler(self.returnStanzaHandler)
|
self.RegisterDefaultHandler(self.returnStanzaHandler)
|
||||||
self.RegisterEventHandler(self._owner._caller._event_dispatcher)
|
self.RegisterEventHandler(self._owner._caller._event_dispatcher)
|
||||||
self.on_responses = {}
|
self.on_responses = {}
|
||||||
|
|
||||||
def plugin(self, owner):
|
def plugin(self, owner):
|
||||||
"""
|
"""
|
||||||
Plug the Dispatcher instance into Client class instance and send initial
|
Plug the Dispatcher instance into Client class instance and send initial
|
||||||
|
@ -416,7 +420,11 @@ class XMPPDispatcher(PlugIn):
|
||||||
typ = ''
|
typ = ''
|
||||||
stanza.props = stanza.getProperties()
|
stanza.props = stanza.getProperties()
|
||||||
ID = stanza.getID()
|
ID = stanza.getID()
|
||||||
|
if self.supports_sm and (stanza.getName() != 'r' and
|
||||||
|
stanza.getName() != 'a' and
|
||||||
|
stanza.getName() != 'enabled') :
|
||||||
|
# increments the number of stanzas that has been handled
|
||||||
|
self.sm.in_h = self.sm.in_h + 1
|
||||||
list_ = ['default'] # we will use all handlers:
|
list_ = ['default'] # we will use all handlers:
|
||||||
if typ in self.handlers[xmlns][name]:
|
if typ in self.handlers[xmlns][name]:
|
||||||
list_.append(typ) # from very common...
|
list_.append(typ) # from very common...
|
||||||
|
|
|
@ -143,7 +143,7 @@ NS_DATA_LAYOUT = 'http://jabber.org/protocol/xdata-layout' # XEP-0141
|
||||||
NS_DATA_VALIDATE = 'http://jabber.org/protocol/xdata-validate' # XEP-0122
|
NS_DATA_VALIDATE = 'http://jabber.org/protocol/xdata-validate' # XEP-0122
|
||||||
NS_XMPP_STREAMS = 'urn:ietf:params:xml:ns:xmpp-streams'
|
NS_XMPP_STREAMS = 'urn:ietf:params:xml:ns:xmpp-streams'
|
||||||
NS_RECEIPTS = 'urn:xmpp:receipts'
|
NS_RECEIPTS = 'urn:xmpp:receipts'
|
||||||
NS_STREAM_MGMT = 'urn:xmpp:sm:3' # XEP-198
|
NS_STREAM_MGMT = 'urn:xmpp:sm:2' # XEP-198
|
||||||
|
|
||||||
xmpp_stream_error_conditions = '''
|
xmpp_stream_error_conditions = '''
|
||||||
bad-format -- -- -- The entity has sent XML that cannot be processed.
|
bad-format -- -- -- The entity has sent XML that cannot be processed.
|
||||||
|
|
44
src/common/xmpp/smacks.py
Normal file
44
src/common/xmpp/smacks.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
from protocol import Acks
|
||||||
|
from protocol import NS_STREAM_MGMT
|
||||||
|
|
||||||
|
class Smacks():
|
||||||
|
'''
|
||||||
|
This is Smacks is the Stream Management class. It takes care of requesting
|
||||||
|
and sending acks. Also, it keeps track of the unhandled outgoing stanzas.
|
||||||
|
|
||||||
|
The dispatcher has to be able to access this class to increment the
|
||||||
|
number of handled stanzas
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, owner):
|
||||||
|
self._owner = owner
|
||||||
|
self.out_h = 0 # Outgoing stanzas handled
|
||||||
|
self.in_h = 0 # Incoming stanzas handled
|
||||||
|
self.uqueue = [] # Unhandled stanzas queue
|
||||||
|
|
||||||
|
#Register handlers
|
||||||
|
owner.Dispatcher.RegisterNamespace(NS_STREAM_MGMT)
|
||||||
|
owner.Dispatcher.RegisterHandler('enabled', self._neg_response
|
||||||
|
,xmlns=NS_STREAM_MGMT)
|
||||||
|
owner.Dispatcher.RegisterHandler('r', self.send_ack
|
||||||
|
,xmlns=NS_STREAM_MGMT)
|
||||||
|
|
||||||
|
|
||||||
|
def negociate(self):
|
||||||
|
stanza = Acks()
|
||||||
|
stanza.buildEnable()
|
||||||
|
self._owner.Connection.send(stanza, True)
|
||||||
|
|
||||||
|
def _neg_response(self, disp, stanza):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def send_ack(self, disp, stanza):
|
||||||
|
ack = Acks()
|
||||||
|
ack.buildAnswer(self.in_h)
|
||||||
|
self._owner.Connection.send(ack, False)
|
||||||
|
|
||||||
|
def request_ack(self):
|
||||||
|
r = Acks()
|
||||||
|
r.buildRequest()
|
||||||
|
self._owner.Connection.send(r, False)
|
Loading…
Add table
Reference in a new issue