Rename client.py to plugin.py, as all client logic has already been moved to client_nb.py
Introduce a get_instance factory method for all plugins and other xmpp related classes. This will help us to decouple plugs in order to make them testable.
This commit is contained in:
parent
e00f871b26
commit
bc3445881f
11 changed files with 75 additions and 42 deletions
|
@ -13,7 +13,7 @@ Thanks and credits to the xmpppy developers. See: http://xmpppy.sourceforge.net/
|
||||||
import simplexml, protocol, auth_nb, transports_nb, roster_nb
|
import simplexml, protocol, auth_nb, transports_nb, roster_nb
|
||||||
import dispatcher_nb, features_nb, idlequeue, bosh, tls_nb, proxy_connectors
|
import dispatcher_nb, features_nb, idlequeue, bosh, tls_nb, proxy_connectors
|
||||||
from client_nb import NonBlockingClient
|
from client_nb import NonBlockingClient
|
||||||
from client import PlugIn
|
from plugin import PlugIn
|
||||||
from protocol import *
|
from protocol import *
|
||||||
|
|
||||||
# vim: se ts=3:
|
# vim: se ts=3:
|
||||||
|
|
|
@ -21,7 +21,7 @@ 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
|
||||||
from protocol import Node, NodeProcessed, isResultNode, Iq, Protocol, JID
|
from protocol import Node, NodeProcessed, isResultNode, Iq, Protocol, JID
|
||||||
from client import PlugIn
|
from plugin import PlugIn
|
||||||
import base64
|
import base64
|
||||||
import random
|
import random
|
||||||
import itertools
|
import itertools
|
||||||
|
@ -127,7 +127,7 @@ class SASL(PlugIn):
|
||||||
self.password = password
|
self.password = password
|
||||||
self.on_sasl = on_sasl
|
self.on_sasl = on_sasl
|
||||||
self.realm = None
|
self.realm = None
|
||||||
|
|
||||||
def plugin(self, owner):
|
def plugin(self, owner):
|
||||||
if 'version' not in self._owner.Dispatcher.Stream._document_attrs:
|
if 'version' not in self._owner.Dispatcher.Stream._document_attrs:
|
||||||
self.startsasl = SASL_UNSUPPORTED
|
self.startsasl = SASL_UNSUPPORTED
|
||||||
|
@ -255,8 +255,8 @@ class SASL(PlugIn):
|
||||||
# Openfire)
|
# Openfire)
|
||||||
old_features = self._owner.Dispatcher.Stream.features
|
old_features = self._owner.Dispatcher.Stream.features
|
||||||
self._owner.Dispatcher.PlugOut()
|
self._owner.Dispatcher.PlugOut()
|
||||||
dispatcher_nb.Dispatcher().PlugIn(self._owner, after_SASL=True,
|
dispatcher_nb.Dispatcher.get_instance().PlugIn(self._owner,
|
||||||
old_features=old_features)
|
after_SASL=True, old_features=old_features)
|
||||||
self._owner.Dispatcher.restoreHandlers(handlers)
|
self._owner.Dispatcher.restoreHandlers(handlers)
|
||||||
self._owner.User = self.username
|
self._owner.User = self.username
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
''' XML canonicalisation methods (for XEP-0116) '''
|
|
||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
## src/common/stanza_session.py
|
## c14n.py
|
||||||
##
|
##
|
||||||
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
|
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
|
||||||
##
|
##
|
||||||
|
@ -18,6 +17,8 @@
|
||||||
## You should have received a copy of the GNU General Public License
|
## You should have received a copy of the GNU General Public License
|
||||||
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||||
##
|
##
|
||||||
|
|
||||||
|
''' XML canonicalisation methods (for XEP-0116) '''
|
||||||
from simplexml import ustr
|
from simplexml import ustr
|
||||||
|
|
||||||
def c14n(node):
|
def c14n(node):
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
## client_nb.py
|
## client_nb.py
|
||||||
## based on client.py, changes backported up to revision 1.60
|
## based on client.py, changes backported up to revision 1.60
|
||||||
|
|
||||||
##
|
##
|
||||||
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
|
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
|
||||||
## modified by Dimitur Kirov <dkirov@gmail.com>
|
## modified by Dimitur Kirov <dkirov@gmail.com>
|
||||||
|
@ -21,9 +20,7 @@
|
||||||
Client class establishs connection to XMPP Server and handles authentication
|
Client class establishs connection to XMPP Server and handles authentication
|
||||||
'''
|
'''
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
import transports_nb, dispatcher_nb, auth_nb, roster_nb, protocol, bosh
|
import transports_nb, dispatcher_nb, auth_nb, roster_nb, protocol, bosh
|
||||||
|
|
||||||
from protocol import NS_TLS
|
from protocol import NS_TLS
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
@ -185,7 +182,7 @@ class NonBlockingClient:
|
||||||
|
|
||||||
if proxy['type'] == 'bosh':
|
if proxy['type'] == 'bosh':
|
||||||
# Setup BOSH transport
|
# Setup BOSH transport
|
||||||
self.socket = bosh.NonBlockingBOSH(
|
self.socket = bosh.NonBlockingBOSH.get_instance(
|
||||||
on_disconnect=self.disconnect,
|
on_disconnect=self.disconnect,
|
||||||
raise_event=self.raise_event,
|
raise_event=self.raise_event,
|
||||||
idlequeue=self.idlequeue,
|
idlequeue=self.idlequeue,
|
||||||
|
@ -206,7 +203,7 @@ class NonBlockingClient:
|
||||||
|
|
||||||
if not proxy or proxy['type'] != 'bosh':
|
if not proxy or proxy['type'] != 'bosh':
|
||||||
# Setup ordinary TCP transport
|
# Setup ordinary TCP transport
|
||||||
self.socket = transports_nb.NonBlockingTCP(
|
self.socket = transports_nb.NonBlockingTCP.get_instance(
|
||||||
on_disconnect=self.disconnect,
|
on_disconnect=self.disconnect,
|
||||||
raise_event=self.raise_event,
|
raise_event=self.raise_event,
|
||||||
idlequeue=self.idlequeue,
|
idlequeue=self.idlequeue,
|
||||||
|
@ -297,7 +294,7 @@ class NonBlockingClient:
|
||||||
if self.__dict__.has_key('Dispatcher'):
|
if self.__dict__.has_key('Dispatcher'):
|
||||||
self.Dispatcher.PlugOut()
|
self.Dispatcher.PlugOut()
|
||||||
self.got_features = False
|
self.got_features = False
|
||||||
dispatcher_nb.Dispatcher().PlugIn(self)
|
dispatcher_nb.Dispatcher.get_instance().PlugIn(self)
|
||||||
on_next_receive('RECEIVE_DOCUMENT_ATTRIBUTES')
|
on_next_receive('RECEIVE_DOCUMENT_ATTRIBUTES')
|
||||||
|
|
||||||
elif mode == 'FAILURE':
|
elif mode == 'FAILURE':
|
||||||
|
@ -451,13 +448,13 @@ class NonBlockingClient:
|
||||||
def _on_doc_attrs(self):
|
def _on_doc_attrs(self):
|
||||||
''' Plug authentication objects and start auth. '''
|
''' Plug authentication objects and start auth. '''
|
||||||
if self._sasl:
|
if self._sasl:
|
||||||
auth_nb.SASL(self._User, self._Password,
|
auth_nb.SASL.get_instance(self._User, self._Password,
|
||||||
self._on_start_sasl).PlugIn(self)
|
self._on_start_sasl).PlugIn(self)
|
||||||
if not self._sasl or self.SASL.startsasl == 'not-supported':
|
if not self._sasl or self.SASL.startsasl == 'not-supported':
|
||||||
if not self._Resource:
|
if not self._Resource:
|
||||||
self._Resource = 'xmpppy'
|
self._Resource = 'xmpppy'
|
||||||
auth_nb.NonBlockingNonSASL(self._User, self._Password, self._Resource,
|
auth_nb.NonBlockingNonSASL.get_instance(self._User, self._Password,
|
||||||
self._on_old_auth).PlugIn(self)
|
self._Resource, self._on_old_auth).PlugIn(self)
|
||||||
return
|
return
|
||||||
self.SASL.auth()
|
self.SASL.auth()
|
||||||
return True
|
return True
|
||||||
|
@ -479,7 +476,7 @@ class NonBlockingClient:
|
||||||
self.connected = None # FIXME: is this intended?
|
self.connected = None # FIXME: is this intended?
|
||||||
self._on_sasl_auth(None)
|
self._on_sasl_auth(None)
|
||||||
elif self.SASL.startsasl == 'success':
|
elif self.SASL.startsasl == 'success':
|
||||||
auth_nb.NonBlockingBind().PlugIn(self)
|
auth_nb.NonBlockingBind.get_instance().PlugIn(self)
|
||||||
self.onreceive(self._on_auth_bind)
|
self.onreceive(self._on_auth_bind)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -495,7 +492,7 @@ class NonBlockingClient:
|
||||||
def initRoster(self):
|
def initRoster(self):
|
||||||
''' Plug in the roster. '''
|
''' Plug in the roster. '''
|
||||||
if not self.__dict__.has_key('NonBlockingRoster'):
|
if not self.__dict__.has_key('NonBlockingRoster'):
|
||||||
roster_nb.NonBlockingRoster().PlugIn(self)
|
roster_nb.NonBlockingRoster.get_instance().PlugIn(self)
|
||||||
|
|
||||||
def getRoster(self, on_ready=None):
|
def getRoster(self, on_ready=None):
|
||||||
''' Return the Roster instance, previously plugging it in and
|
''' Return the Roster instance, previously plugging it in and
|
||||||
|
@ -509,7 +506,7 @@ class NonBlockingClient:
|
||||||
Can also request roster from server if according agrument is set.'''
|
Can also request roster from server if according agrument is set.'''
|
||||||
if requestRoster:
|
if requestRoster:
|
||||||
# FIXME: used somewhere?
|
# FIXME: used somewhere?
|
||||||
roster_nb.NonBlockingRoster().PlugIn(self)
|
roster_nb.NonBlockingRoster.get_instance().PlugIn(self)
|
||||||
self.send(dispatcher_nb.Presence(to=jid, typ=typ))
|
self.send(dispatcher_nb.Presence(to=jid, typ=typ))
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
|
@ -22,9 +22,9 @@ different handlers to different XMPP stanzas and namespaces.
|
||||||
|
|
||||||
import simplexml, sys, locale
|
import simplexml, sys, locale
|
||||||
from xml.parsers.expat import ExpatError
|
from xml.parsers.expat import ExpatError
|
||||||
from client import PlugIn
|
from plugin import PlugIn
|
||||||
from protocol import NS_STREAMS, NS_XMPP_STREAMS, NS_HTTP_BIND, Iq, Presence, \
|
from protocol import (NS_STREAMS, NS_XMPP_STREAMS, NS_HTTP_BIND, Iq, Presence,
|
||||||
Message, Protocol, Node, Error, ERR_FEATURE_NOT_IMPLEMENTED, StreamError
|
Message, Protocol, Node, Error, ERR_FEATURE_NOT_IMPLEMENTED, StreamError)
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger('gajim.c.x.dispatcher_nb')
|
log = logging.getLogger('gajim.c.x.dispatcher_nb')
|
||||||
|
|
||||||
|
@ -52,6 +52,16 @@ class Dispatcher():
|
||||||
XMPPDispatcher().PlugIn(client_obj)
|
XMPPDispatcher().PlugIn(client_obj)
|
||||||
elif client_obj.protocol_type == 'BOSH':
|
elif client_obj.protocol_type == 'BOSH':
|
||||||
BOSHDispatcher().PlugIn(client_obj, after_SASL, old_features)
|
BOSHDispatcher().PlugIn(client_obj, after_SASL, old_features)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_instance(cls, *args, **kwargs):
|
||||||
|
'''
|
||||||
|
Factory Method for object creation.
|
||||||
|
|
||||||
|
Use this instead of directly initializing the class in order to make
|
||||||
|
unit testing much easier.
|
||||||
|
'''
|
||||||
|
return cls(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class XMPPDispatcher(PlugIn):
|
class XMPPDispatcher(PlugIn):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
## client.py
|
## plugin.py
|
||||||
##
|
##
|
||||||
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
|
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
|
||||||
##
|
##
|
||||||
|
@ -82,5 +82,16 @@ class PlugIn:
|
||||||
if hasattr(self,'plugout'):
|
if hasattr(self,'plugout'):
|
||||||
return self.plugout()
|
return self.plugout()
|
||||||
del self._owner
|
del self._owner
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_instance(cls, *args, **kwargs):
|
||||||
|
'''
|
||||||
|
Factory Method for object creation.
|
||||||
|
|
||||||
|
Use this instead of directly initializing the class in order to make
|
||||||
|
unit testing easier. For testing, this method can be patched to inject
|
||||||
|
mock objects.
|
||||||
|
'''
|
||||||
|
return cls(*args, **kwargs)
|
||||||
|
|
||||||
# vim: se ts=3:
|
# vim: se ts=3:
|
|
@ -55,6 +55,16 @@ class ProxyConnector:
|
||||||
self.old_on_receive = old_on_receive
|
self.old_on_receive = old_on_receive
|
||||||
|
|
||||||
self.start_connecting()
|
self.start_connecting()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_instance(cls, *args, **kwargs):
|
||||||
|
'''
|
||||||
|
Factory Method for object creation.
|
||||||
|
|
||||||
|
Use this instead of directly initializing the class in order to make
|
||||||
|
unit testing much easier.
|
||||||
|
'''
|
||||||
|
return cls(*args, **kwargs)
|
||||||
|
|
||||||
def start_connecting(self):
|
def start_connecting(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
|
@ -22,7 +22,7 @@ mass-renaming of contacts.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from protocol import JID, Iq, Presence, Node, NodeProcessed, NS_ROSTER
|
from protocol import JID, Iq, Presence, Node, NodeProcessed, NS_ROSTER
|
||||||
from client import PlugIn
|
from plugin import PlugIn
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger('gajim.c.x.roster_nb')
|
log = logging.getLogger('gajim.c.x.roster_nb')
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
from client import PlugIn
|
from plugin import PlugIn
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
|
@ -25,7 +25,7 @@ connection handling.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from simplexml import ustr
|
from simplexml import ustr
|
||||||
from client import PlugIn
|
from plugin import PlugIn
|
||||||
from idlequeue import IdleObject
|
from idlequeue import IdleObject
|
||||||
import proxy_connectors
|
import proxy_connectors
|
||||||
import tls_nb
|
import tls_nb
|
||||||
|
@ -74,22 +74,27 @@ DISCONNECT_TIMEOUT_SECONDS = 5
|
||||||
#: size of the buffer which reads data from server
|
#: size of the buffer which reads data from server
|
||||||
# if lower, more stanzas will be fragmented and processed twice
|
# if lower, more stanzas will be fragmented and processed twice
|
||||||
RECV_BUFSIZE = 32768 # 2x maximum size of ssl packet, should be plenty
|
RECV_BUFSIZE = 32768 # 2x maximum size of ssl packet, should be plenty
|
||||||
#RECV_BUFSIZE = 16 # FIXME: (#2634) gajim breaks with this setting: it's inefficient but should work.
|
# FIXME: (#2634) gajim breaks with #RECV_BUFSIZE = 16
|
||||||
|
# it's inefficient but should work. Problem is that connect machine makes wrong
|
||||||
|
# assumptions and that we only check for pending data in sockets but not in SSL
|
||||||
|
# buffer...
|
||||||
|
|
||||||
DATA_RECEIVED='DATA RECEIVED'
|
DATA_RECEIVED = 'DATA RECEIVED'
|
||||||
DATA_SENT='DATA SENT'
|
DATA_SENT = 'DATA SENT'
|
||||||
|
|
||||||
DISCONNECTED = 'DISCONNECTED'
|
DISCONNECTED = 'DISCONNECTED'
|
||||||
DISCONNECTING = 'DISCONNECTING'
|
DISCONNECTING = 'DISCONNECTING'
|
||||||
CONNECTING = 'CONNECTING'
|
CONNECTING = 'CONNECTING'
|
||||||
PROXY_CONNECTING = 'PROXY_CONNECTING'
|
PROXY_CONNECTING = 'PROXY_CONNECTING'
|
||||||
CONNECTED = 'CONNECTED'
|
CONNECTED = 'CONNECTED'
|
||||||
STATES = [DISCONNECTED, CONNECTING, PROXY_CONNECTING, CONNECTED, DISCONNECTING]
|
STATES = (DISCONNECTED, CONNECTING, PROXY_CONNECTING, CONNECTED, DISCONNECTING)
|
||||||
# Transports have different arguments in constructor and same connect() method.
|
|
||||||
|
|
||||||
class NonBlockingTransport(PlugIn):
|
class NonBlockingTransport(PlugIn):
|
||||||
'''
|
'''
|
||||||
Abstract class representing a transport.
|
Abstract class representing a transport.
|
||||||
|
|
||||||
|
Subclasses CAN have different constructor signature but connect method SHOULD
|
||||||
|
be the same.
|
||||||
'''
|
'''
|
||||||
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
|
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
|
||||||
certs):
|
certs):
|
||||||
|
@ -322,15 +327,14 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
proxyclass = proxy_connectors.SOCKS5Connector
|
proxyclass = proxy_connectors.SOCKS5Connector
|
||||||
elif self.proxy_dict['type'] == 'http' :
|
elif self.proxy_dict['type'] == 'http' :
|
||||||
proxyclass = proxy_connectors.HTTPCONNECTConnector
|
proxyclass = proxy_connectors.HTTPCONNECTConnector
|
||||||
proxyclass(
|
proxyclass.get_instance(
|
||||||
send_method = self.send,
|
send_method=self.send,
|
||||||
onreceive = self.onreceive,
|
onreceive=self.onreceive,
|
||||||
old_on_receive = self.on_receive,
|
old_on_receive=self.on_receive,
|
||||||
on_success = self._on_connect,
|
on_success=self._on_connect,
|
||||||
on_failure = self._on_connect_failure,
|
on_failure=self._on_connect_failure,
|
||||||
xmpp_server = self.proxy_dict['xmpp_server'],
|
xmpp_server=self.proxy_dict['xmpp_server'],
|
||||||
proxy_creds = self.proxy_dict['credentials']
|
proxy_creds=self.proxy_dict['credentials'])
|
||||||
)
|
|
||||||
|
|
||||||
def _on_connect(self):
|
def _on_connect(self):
|
||||||
'''
|
'''
|
||||||
|
@ -351,7 +355,7 @@ class NonBlockingTCP(NonBlockingTransport, IdleObject):
|
||||||
NonBlockingTLS module
|
NonBlockingTLS module
|
||||||
'''
|
'''
|
||||||
cacerts, mycerts = self.certs
|
cacerts, mycerts = self.certs
|
||||||
result = tls_nb.NonBlockingTLS(cacerts, mycerts).PlugIn(self)
|
result = tls_nb.NonBlockingTLS.get_instance(cacerts, mycerts).PlugIn(self)
|
||||||
if result:
|
if result:
|
||||||
on_succ()
|
on_succ()
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -21,7 +21,7 @@ from common import gajim
|
||||||
import common.xmpp
|
import common.xmpp
|
||||||
from common.xmpp.idlequeue import IdleObject
|
from common.xmpp.idlequeue import IdleObject
|
||||||
from common.xmpp import dispatcher_nb, simplexml
|
from common.xmpp import dispatcher_nb, simplexml
|
||||||
from common.xmpp.client import *
|
from common.xmpp.plugin import *
|
||||||
from common.xmpp.simplexml import ustr
|
from common.xmpp.simplexml import ustr
|
||||||
from common.xmpp.transports_nb import DATA_RECEIVED, DATA_SENT
|
from common.xmpp.transports_nb import DATA_RECEIVED, DATA_SENT
|
||||||
from common.zeroconf import zeroconf
|
from common.zeroconf import zeroconf
|
||||||
|
|
Loading…
Add table
Reference in a new issue