Coding standards and documentation improvements in client_nb.py
This commit is contained in:
parent
5139e7c8d0
commit
40d802284e
|
@ -16,10 +16,13 @@
|
||||||
|
|
||||||
# $Id: client.py,v 1.52 2006/01/02 19:40:55 normanr Exp $
|
# $Id: client.py,v 1.52 2006/01/02 19:40:55 normanr Exp $
|
||||||
|
|
||||||
|
'''
|
||||||
|
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 client import *
|
from client import PlugIn
|
||||||
|
|
||||||
from protocol import NS_TLS
|
from protocol import NS_TLS
|
||||||
|
|
||||||
|
@ -37,10 +40,11 @@ class NonBlockingClient:
|
||||||
def __init__(self, domain, idlequeue, caller=None):
|
def __init__(self, domain, idlequeue, caller=None):
|
||||||
'''
|
'''
|
||||||
Caches connection data:
|
Caches connection data:
|
||||||
|
|
||||||
:param domain: domain - for to: attribute (from account info)
|
:param domain: domain - for to: attribute (from account info)
|
||||||
:param idlequeue: processing idlequeue
|
:param idlequeue: processing idlequeue
|
||||||
:param caller: calling object - it has to implement methods _event_dispatcher
|
:param caller: calling object - it has to implement methods
|
||||||
which is called from dispatcher instance
|
_event_dispatcher which is called from dispatcher instance
|
||||||
'''
|
'''
|
||||||
self.Namespace = protocol.NS_CLIENT
|
self.Namespace = protocol.NS_CLIENT
|
||||||
self.defaultNamespace = self.Namespace
|
self.defaultNamespace = self.Namespace
|
||||||
|
@ -51,7 +55,8 @@ class NonBlockingClient:
|
||||||
self.Server = domain
|
self.Server = domain
|
||||||
self.xmpp_hostname = None # FQDN hostname to connect to
|
self.xmpp_hostname = None # FQDN hostname to connect to
|
||||||
|
|
||||||
# caller is who initiated this client, it is ineeded to register the EventDispatcher
|
# caller is who initiated this client, it is in needed to register
|
||||||
|
# the EventDispatcher
|
||||||
self._caller = caller
|
self._caller = caller
|
||||||
self._owner = self
|
self._owner = self
|
||||||
self._registered_name = None
|
self._registered_name = None
|
||||||
|
@ -68,10 +73,9 @@ class NonBlockingClient:
|
||||||
|
|
||||||
def disconnect(self, message=''):
|
def disconnect(self, message=''):
|
||||||
'''
|
'''
|
||||||
Called on disconnection - disconnect callback is picked based on state of the
|
Called on disconnection - disconnect callback is picked based on state
|
||||||
client.
|
of the client.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# to avoid recursive calls
|
# to avoid recursive calls
|
||||||
if self.disconnecting: return
|
if self.disconnecting: return
|
||||||
|
|
||||||
|
@ -102,8 +106,8 @@ class NonBlockingClient:
|
||||||
|
|
||||||
log.debug('Client disconnected..')
|
log.debug('Client disconnected..')
|
||||||
if connected == '':
|
if connected == '':
|
||||||
# if we're disconnecting before connection to XMPP sever is opened, we don't
|
# if we're disconnecting before connection to XMPP sever is opened,
|
||||||
# call disconnect handlers but on_connect_failure callback
|
# we don't call disconnect handlers but on_connect_failure callback
|
||||||
if self.proxy:
|
if self.proxy:
|
||||||
# with proxy, we have different failure callback
|
# with proxy, we have different failure callback
|
||||||
log.debug('calling on_proxy_failure cb')
|
log.debug('calling on_proxy_failure cb')
|
||||||
|
@ -114,9 +118,10 @@ class NonBlockingClient:
|
||||||
else:
|
else:
|
||||||
# we are connected to XMPP server
|
# we are connected to XMPP server
|
||||||
if not stream_started:
|
if not stream_started:
|
||||||
# if error occur before XML stream was opened, e.g. no response on init
|
# if error occur before XML stream was opened, e.g. no response on
|
||||||
# request, we call the on_connect_failure callback because proper
|
# init request, we call the on_connect_failure callback because
|
||||||
# connection is not estabilished yet and it's not a proxy issue
|
# proper connection is not estabilished yet and it's not a proxy
|
||||||
|
# issue
|
||||||
log.debug('calling on_connect_failure cb')
|
log.debug('calling on_connect_failure cb')
|
||||||
self.on_connect_failure()
|
self.on_connect_failure()
|
||||||
else:
|
else:
|
||||||
|
@ -126,26 +131,26 @@ class NonBlockingClient:
|
||||||
i()
|
i()
|
||||||
self.disconnecting = False
|
self.disconnecting = False
|
||||||
|
|
||||||
|
|
||||||
def connect(self, on_connect, on_connect_failure, hostname=None, port=5222,
|
def connect(self, on_connect, on_connect_failure, hostname=None, port=5222,
|
||||||
on_proxy_failure=None, proxy=None, secure_tuple=(None, None, None)):
|
on_proxy_failure=None, proxy=None, secure_tuple=(None, None, None)):
|
||||||
'''
|
'''
|
||||||
Open XMPP connection (open XML streams in both directions).
|
Open XMPP connection (open XML streams in both directions).
|
||||||
|
|
||||||
:param on_connect: called after stream is successfully opened
|
:param on_connect: called after stream is successfully opened
|
||||||
:param on_connect_failure: called when error occures during connection
|
:param on_connect_failure: called when error occures during connection
|
||||||
:param hostname: hostname of XMPP server from SRV request
|
:param hostname: hostname of XMPP server from SRV request
|
||||||
:param port: port number of XMPP server
|
:param port: port number of XMPP server
|
||||||
:param on_proxy_failure: called if error occurres during TCP connection to
|
:param on_proxy_failure: called if error occurres during TCP connection to
|
||||||
proxy server or during proxy connecting process
|
proxy server or during proxy connecting process
|
||||||
:param proxy: dictionary with proxy data. It should contain at least values
|
:param proxy: dictionary with proxy data. It should contain at least
|
||||||
for keys 'host' and 'port' - connection details for proxy server and
|
values for keys 'host' and 'port' - connection details for proxy serve
|
||||||
optionally keys 'user' and 'pass' as proxy credentials
|
and optionally keys 'user' and 'pass' as proxy credentials
|
||||||
:param secure_tuple: tuple of (desired connection type, cacerts and mycerts)
|
:param secure_tuple: tuple of (desired connection type, cacerts, mycerts)
|
||||||
connection type can be 'ssl' - TLS estabilished after TCP connection,
|
connection type can be 'ssl' - TLS estabilished after TCP connection,
|
||||||
'tls' - TLS estabilished after negotiation with starttls, or 'plain'.
|
'tls' - TLS estabilished after negotiation with starttls, or 'plain'.
|
||||||
cacerts, mycerts - see tls_nb.NonBlockingTLS constructor for more details
|
cacerts, mycerts - see tls_nb.NonBlockingTLS constructor for more
|
||||||
|
details
|
||||||
'''
|
'''
|
||||||
|
|
||||||
self.on_connect = on_connect
|
self.on_connect = on_connect
|
||||||
self.on_connect_failure=on_connect_failure
|
self.on_connect_failure=on_connect_failure
|
||||||
self.on_proxy_failure = on_proxy_failure
|
self.on_proxy_failure = on_proxy_failure
|
||||||
|
@ -173,9 +178,9 @@ class NonBlockingClient:
|
||||||
# (DNS request will be done for proxy or BOSH CM hostname)
|
# (DNS request will be done for proxy or BOSH CM hostname)
|
||||||
tcp_host, tcp_port, proxy_user, proxy_pass = \
|
tcp_host, tcp_port, proxy_user, proxy_pass = \
|
||||||
transports_nb.get_proxy_data_from_dict(proxy)
|
transports_nb.get_proxy_data_from_dict(proxy)
|
||||||
|
|
||||||
|
|
||||||
if proxy['type'] == 'bosh':
|
if proxy['type'] == 'bosh':
|
||||||
|
# Setup BOSH transport
|
||||||
self.socket = bosh.NonBlockingBOSH(
|
self.socket = bosh.NonBlockingBOSH(
|
||||||
on_disconnect = self.disconnect,
|
on_disconnect = self.disconnect,
|
||||||
raise_event = self.raise_event,
|
raise_event = self.raise_event,
|
||||||
|
@ -187,14 +192,16 @@ class NonBlockingClient:
|
||||||
domain = self.Server,
|
domain = self.Server,
|
||||||
bosh_dict = proxy)
|
bosh_dict = proxy)
|
||||||
self.protocol_type = 'BOSH'
|
self.protocol_type = 'BOSH'
|
||||||
self.wait_for_restart_response = proxy['bosh_wait_for_restart_response']
|
self.wait_for_restart_response = \
|
||||||
|
proxy['bosh_wait_for_restart_response']
|
||||||
else:
|
else:
|
||||||
|
# http proxy
|
||||||
proxy_dict['type'] = proxy['type']
|
proxy_dict['type'] = proxy['type']
|
||||||
proxy_dict['xmpp_server'] = (self.xmpp_hostname, self.Port)
|
proxy_dict['xmpp_server'] = (self.xmpp_hostname, self.Port)
|
||||||
proxy_dict['credentials'] = (proxy_user, proxy_pass)
|
proxy_dict['credentials'] = (proxy_user, proxy_pass)
|
||||||
|
|
||||||
if not proxy or proxy['type'] != 'bosh':
|
if not proxy or proxy['type'] != 'bosh':
|
||||||
|
# Setup ordinary TCP transport
|
||||||
self.socket = transports_nb.NonBlockingTCP(
|
self.socket = transports_nb.NonBlockingTCP(
|
||||||
on_disconnect = self.disconnect,
|
on_disconnect = self.disconnect,
|
||||||
raise_event = self.raise_event,
|
raise_event = self.raise_event,
|
||||||
|
@ -203,6 +210,7 @@ class NonBlockingClient:
|
||||||
certs = certs,
|
certs = certs,
|
||||||
proxy_dict = proxy_dict)
|
proxy_dict = proxy_dict)
|
||||||
|
|
||||||
|
# plug transport into client as self.Connection
|
||||||
self.socket.PlugIn(self)
|
self.socket.PlugIn(self)
|
||||||
|
|
||||||
self._resolve_hostname(
|
self._resolve_hostname(
|
||||||
|
@ -222,7 +230,7 @@ class NonBlockingClient:
|
||||||
on_success()
|
on_success()
|
||||||
|
|
||||||
def _try_next_ip(self, err_message=None):
|
def _try_next_ip(self, err_message=None):
|
||||||
'''iterates over IP addresses from getaddrinfo'''
|
'''Iterates over IP addresses tries to connect to it'''
|
||||||
if err_message:
|
if err_message:
|
||||||
log.debug('While looping over DNS A records: %s' % err_message)
|
log.debug('While looping over DNS A records: %s' % err_message)
|
||||||
if self.ip_addresses == []:
|
if self.ip_addresses == []:
|
||||||
|
@ -236,10 +244,9 @@ class NonBlockingClient:
|
||||||
on_connect=lambda: self._xmpp_connect(socket_type='plain'),
|
on_connect=lambda: self._xmpp_connect(socket_type='plain'),
|
||||||
on_connect_failure=self._try_next_ip)
|
on_connect_failure=self._try_next_ip)
|
||||||
|
|
||||||
|
|
||||||
def incoming_stream_version(self):
|
def incoming_stream_version(self):
|
||||||
''' gets version of xml stream'''
|
''' gets version of xml stream'''
|
||||||
if self.Dispatcher.Stream._document_attrs.has_key('version'):
|
if 'version' in self.Dispatcher.Stream._document_attrs:
|
||||||
return self.Dispatcher.Stream._document_attrs['version']
|
return self.Dispatcher.Stream._document_attrs['version']
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
@ -255,19 +262,23 @@ class NonBlockingClient:
|
||||||
self.connected = socket_type
|
self.connected = socket_type
|
||||||
self._xmpp_connect_machine()
|
self._xmpp_connect_machine()
|
||||||
|
|
||||||
|
|
||||||
def _xmpp_connect_machine(self, mode=None, data=None):
|
def _xmpp_connect_machine(self, mode=None, data=None):
|
||||||
'''
|
'''
|
||||||
Finite automaton taking care of stream opening and features tag
|
Finite automaton taking care of stream opening and features tag
|
||||||
handling. Calls _on_stream_start when stream is started, and disconnect()
|
handling. Calls _on_stream_start when stream is started, and disconnect()
|
||||||
on failure.
|
on failure.
|
||||||
'''
|
'''
|
||||||
log.info('-------------xmpp_connect_machine() >> mode: %s, data: %s...' % (mode,str(data)[:20] ))
|
log.info('-------------xmpp_connect_machine() >> mode: %s, data: %s...' %
|
||||||
|
(mode, str(data)[:20]))
|
||||||
|
|
||||||
def on_next_receive(mode):
|
def on_next_receive(mode):
|
||||||
|
'''
|
||||||
|
Sets desired on_receive callback on transport based on the state of
|
||||||
|
connect_machine.
|
||||||
|
'''
|
||||||
log.info('setting %s on next receive' % mode)
|
log.info('setting %s on next receive' % mode)
|
||||||
if mode is None:
|
if mode is None:
|
||||||
self.onreceive(None)
|
self.onreceive(None) # switch to Dispatcher.ProcessNonBlocking
|
||||||
else:
|
else:
|
||||||
self.onreceive(lambda _data:self._xmpp_connect_machine(mode, _data))
|
self.onreceive(lambda _data:self._xmpp_connect_machine(mode, _data))
|
||||||
|
|
||||||
|
@ -286,7 +297,7 @@ class NonBlockingClient:
|
||||||
if data:
|
if data:
|
||||||
self.Dispatcher.ProcessNonBlocking(data)
|
self.Dispatcher.ProcessNonBlocking(data)
|
||||||
if not hasattr(self, 'Dispatcher') or \
|
if not hasattr(self, 'Dispatcher') or \
|
||||||
self.Dispatcher.Stream._document_attrs is None:
|
self.Dispatcher.Stream._document_attrs is None:
|
||||||
self._xmpp_connect_machine(
|
self._xmpp_connect_machine(
|
||||||
mode='FAILURE',
|
mode='FAILURE',
|
||||||
data='Error on stream open')
|
data='Error on stream open')
|
||||||
|
@ -320,7 +331,7 @@ class NonBlockingClient:
|
||||||
def _on_stream_start(self):
|
def _on_stream_start(self):
|
||||||
'''
|
'''
|
||||||
Called after XMPP stream is opened.
|
Called after XMPP stream is opened.
|
||||||
TLS negotiation may follow after esabilishing a stream.
|
TLS negotiation may follow when stream is established.
|
||||||
'''
|
'''
|
||||||
self.stream_started = True
|
self.stream_started = True
|
||||||
self.onreceive(None)
|
self.onreceive(None)
|
||||||
|
@ -358,7 +369,7 @@ class NonBlockingClient:
|
||||||
self.send('<starttls xmlns="%s"/>' % NS_TLS)
|
self.send('<starttls xmlns="%s"/>' % NS_TLS)
|
||||||
else:
|
else:
|
||||||
# we got <proceed> or <failure>
|
# we got <proceed> or <failure>
|
||||||
if tag.getNamespace() <> NS_TLS:
|
if tag.getNamespace() != NS_TLS:
|
||||||
self.disconnect('Unknown namespace: %s' % tag.getNamespace())
|
self.disconnect('Unknown namespace: %s' % tag.getNamespace())
|
||||||
return
|
return
|
||||||
tagname = tag.getName()
|
tagname = tag.getName()
|
||||||
|
@ -379,15 +390,17 @@ class NonBlockingClient:
|
||||||
|
|
||||||
def raise_event(self, event_type, data):
|
def raise_event(self, event_type, data):
|
||||||
'''
|
'''
|
||||||
raises event to connection instance - DATA_SENT and DATA_RECIVED events are
|
Raises event to connection instance. DATA_SENT and DATA_RECIVED events
|
||||||
used in XML console to show XMPP traffic
|
are used in XML console to show XMPP traffic
|
||||||
'''
|
'''
|
||||||
log.info('raising event from transport: :::::%s::::\n_____________\n%s\n_____________\n' % (event_type,data))
|
log.info('raising event from transport: :::::%s::::\n_____________\n%s\n_____________\n' % (event_type,data))
|
||||||
if hasattr(self, 'Dispatcher'):
|
if hasattr(self, 'Dispatcher'):
|
||||||
self.Dispatcher.Event('', event_type, data)
|
self.Dispatcher.Event('', event_type, data)
|
||||||
|
|
||||||
# follows code for authentication, resource bind, session and roster download
|
###############################################################################
|
||||||
#
|
### follows code for authentication, resource bind, session and roster download
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
def auth(self, user, password, resource = '', sasl = 1, on_auth = None):
|
def auth(self, user, password, resource = '', sasl = 1, on_auth = None):
|
||||||
'''
|
'''
|
||||||
Authenticate connnection and bind resource. If resource is not provided
|
Authenticate connnection and bind resource. If resource is not provided
|
||||||
|
@ -450,13 +463,12 @@ class NonBlockingClient:
|
||||||
else:
|
else:
|
||||||
self.on_auth(self, None)
|
self.on_auth(self, None)
|
||||||
|
|
||||||
|
|
||||||
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().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
|
||||||
requesting roster from server if needed. '''
|
requesting roster from server if needed. '''
|
||||||
if self.__dict__.has_key('NonBlockingRoster'):
|
if self.__dict__.has_key('NonBlockingRoster'):
|
||||||
|
@ -466,10 +478,15 @@ class NonBlockingClient:
|
||||||
def sendPresence(self, jid=None, typ=None, requestRoster=0):
|
def sendPresence(self, jid=None, typ=None, requestRoster=0):
|
||||||
''' Send some specific presence state.
|
''' Send some specific presence state.
|
||||||
Can also request roster from server if according agrument is set.'''
|
Can also request roster from server if according agrument is set.'''
|
||||||
if requestRoster: roster_nb.NonBlockingRoster().PlugIn(self)
|
if requestRoster:
|
||||||
|
# FIXME: used somewhere?
|
||||||
|
roster_nb.NonBlockingRoster().PlugIn(self)
|
||||||
self.send(dispatcher_nb.Presence(to=jid, typ=typ))
|
self.send(dispatcher_nb.Presence(to=jid, typ=typ))
|
||||||
|
|
||||||
# following methods are moved from blocking client class from xmpppy:
|
###############################################################################
|
||||||
|
### following methods are moved from blocking client class of xmpppy
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
def RegisterDisconnectHandler(self,handler):
|
def RegisterDisconnectHandler(self,handler):
|
||||||
''' Register handler that will be called on disconnect.'''
|
''' Register handler that will be called on disconnect.'''
|
||||||
self.disconnect_handlers.append(handler)
|
self.disconnect_handlers.append(handler)
|
||||||
|
@ -493,8 +510,8 @@ class NonBlockingClient:
|
||||||
def get_peerhost(self):
|
def get_peerhost(self):
|
||||||
'''
|
'''
|
||||||
Gets the ip address of the account, from which is made connection to the
|
Gets the ip address of the account, from which is made connection to the
|
||||||
server , (e.g. IP and port of gajim's socket. We will create listening socket
|
server (e.g. IP and port of gajim's socket).
|
||||||
on the same ip
|
We will create listening socket on the same ip
|
||||||
'''
|
'''
|
||||||
# FIXME: tuple (ip, port) is expected (and checked for) but port num is
|
# FIXME: tuple (ip, port) is expected (and checked for) but port num is
|
||||||
# useless
|
# useless
|
||||||
|
|
Loading…
Reference in New Issue