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
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
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 plugin import PlugIn
 | 
			
		||||
import base64
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ import dispatcher_nb
 | 
			
		|||
import hashlib
 | 
			
		||||
import hmac
 | 
			
		||||
import hashlib
 | 
			
		||||
 | 
			
		||||
from smacks import Smacks
 | 
			
		||||
import logging
 | 
			
		||||
log = logging.getLogger('gajim.c.x.auth_nb')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -491,7 +491,8 @@ class NonBlockingNonSASL(PlugIn):
 | 
			
		|||
            self.password = password
 | 
			
		||||
        self.resource = resource
 | 
			
		||||
        self.on_auth = on_auth
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
    def plugin(self, owner):
 | 
			
		||||
        """
 | 
			
		||||
        Determine the best auth method (digest/0k/plain) and use it for auth.
 | 
			
		||||
| 
						 | 
				
			
			@ -564,6 +565,7 @@ class NonBlockingBind(PlugIn):
 | 
			
		|||
    def __init__(self):
 | 
			
		||||
        PlugIn.__init__(self)
 | 
			
		||||
        self.bound = None
 | 
			
		||||
        self.supports_sm = False
 | 
			
		||||
 | 
			
		||||
    def plugin(self, owner):
 | 
			
		||||
        ''' Start resource binding, if allowed at this time. Used internally. '''
 | 
			
		||||
| 
						 | 
				
			
			@ -580,8 +582,14 @@ class NonBlockingBind(PlugIn):
 | 
			
		|||
    def FeaturesHandler(self, conn, feats):
 | 
			
		||||
        """
 | 
			
		||||
        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):
 | 
			
		||||
            log.info('Server does not requested binding.')
 | 
			
		||||
            # we try to bind resource anyway
 | 
			
		||||
| 
						 | 
				
			
			@ -625,6 +633,14 @@ class NonBlockingBind(PlugIn):
 | 
			
		|||
                jid = JID(resp.getTag('bind').getTagData('jid'))
 | 
			
		||||
                self._owner.User = jid.getNode()
 | 
			
		||||
                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:
 | 
			
		||||
                    # Server don't want us to initialize a session
 | 
			
		||||
                    log.info('No session required.')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,7 +75,7 @@ class XMPPDispatcher(PlugIn):
 | 
			
		|||
    stream headers (used by SASL f.e.).
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
    def __init__(self):        
 | 
			
		||||
        PlugIn.__init__(self)
 | 
			
		||||
        self.handlers = {}
 | 
			
		||||
        self._expected = {}
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +89,9 @@ class XMPPDispatcher(PlugIn):
 | 
			
		|||
                self.UnregisterHandler, self.RegisterProtocol,
 | 
			
		||||
                self.SendAndWaitForResponse, self.SendAndCallForResponse,
 | 
			
		||||
                self.getAnID, self.Event, self.send]
 | 
			
		||||
        
 | 
			
		||||
        # Let the dispatcher know if there is support for stream management
 | 
			
		||||
        self.supports_sm = False 
 | 
			
		||||
 | 
			
		||||
    def getAnID(self):
 | 
			
		||||
        global outgoingID
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +113,7 @@ class XMPPDispatcher(PlugIn):
 | 
			
		|||
        """
 | 
			
		||||
        self.handlers = handlers
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
    def _init(self):
 | 
			
		||||
        """
 | 
			
		||||
        Register default namespaces/protocols/handlers. Used internally
 | 
			
		||||
| 
						 | 
				
			
			@ -125,7 +129,7 @@ class XMPPDispatcher(PlugIn):
 | 
			
		|||
        self.RegisterDefaultHandler(self.returnStanzaHandler)
 | 
			
		||||
        self.RegisterEventHandler(self._owner._caller._event_dispatcher)
 | 
			
		||||
        self.on_responses = {}
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
    def plugin(self, owner):
 | 
			
		||||
        """
 | 
			
		||||
        Plug the Dispatcher instance into Client class instance and send initial
 | 
			
		||||
| 
						 | 
				
			
			@ -416,7 +420,11 @@ class XMPPDispatcher(PlugIn):
 | 
			
		|||
            typ = ''
 | 
			
		||||
        stanza.props = stanza.getProperties()
 | 
			
		||||
        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:
 | 
			
		||||
        if typ in self.handlers[xmlns][name]:
 | 
			
		||||
            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_XMPP_STREAMS   = 'urn:ietf:params:xml:ns:xmpp-streams'
 | 
			
		||||
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 = '''
 | 
			
		||||
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