diff --git a/src/common/xmpp/auth_nb.py b/src/common/xmpp/auth_nb.py
index a05f82481..d8c045e0d 100644
--- a/src/common/xmpp/auth_nb.py
+++ b/src/common/xmpp/auth_nb.py
@@ -173,11 +173,8 @@ class SASL(PlugIn):
self.startsasl='success'
log.info('Successfully authenticated with remote server.')
handlers=self._owner.Dispatcher.dumpHandlers()
- print '6' * 79
- print handlers
- print '6' * 79
self._owner.Dispatcher.PlugOut()
- dispatcher_nb.Dispatcher().PlugIn(self._owner)
+ dispatcher_nb.Dispatcher().PlugIn(self._owner, after_SASL=True)
self._owner.Dispatcher.restoreHandlers(handlers)
self._owner.User = self.username
if self.on_sasl :
diff --git a/src/common/xmpp/bosh.py b/src/common/xmpp/bosh.py
index e41322973..851d7cc4c 100644
--- a/src/common/xmpp/bosh.py
+++ b/src/common/xmpp/bosh.py
@@ -1,80 +1,208 @@
-import protocol, simplexml, locale, random, dispatcher_nb
+import protocol, locale, random, dispatcher_nb
from client_nb import NBCommonClient
+import transports_nb
import logging
+from simplexml import Node
log = logging.getLogger('gajim.c.x.bosh')
class BOSHClient(NBCommonClient):
'''
- Client class implementing BOSH.
+ Client class implementing BOSH. Extends common XMPP
'''
- def __init__(self, *args, **kw):
+ def __init__(self, domain, idlequeue, caller=None):
'''Preceeds constructor of NBCommonClient and sets some of values that will
be used as attributes in
tag'''
- self.Namespace = protocol.NS_HTTP_BIND
- # BOSH parameters should be given via Advanced Configuration Editor
- self.bosh_xml_lang = None
- self.bosh_hold = 1
- self.bosh_wait=60
- self.bosh_rid=None
self.bosh_sid=None
- self.bosh_httpversion = 'HTTP/1.1'
- NBCommonClient.__init__(self, *args, **kw)
-
-
- def connect(self, *args, **kw):
-
-
- if locale.getdefaultlocale()[0]:
- self.bosh_xml_lang = locale.getdefaultlocale()[0].split('_')[0]
-
# with 50-bit random initial rid, session would have to go up
# to 7881299347898368 messages to raise rid over 2**53
# (see http://www.xmpp.org/extensions/xep-0124.html#rids)
r = random.Random()
r.seed()
self.bosh_rid = r.getrandbits(50)
+ self.bosh_sid = None
+
+ if locale.getdefaultlocale()[0]:
+ self.bosh_xml_lang = locale.getdefaultlocale()[0].split('_')[0]
+ else:
+ self.bosh_xml_lang = 'en'
+
+ self.http_version = 'HTTP/1.1'
+ self.bosh_to = domain
+
+ #self.Namespace = protocol.NS_HTTP_BIND
+ #self.defaultNamespace = self.Namespace
+ self.bosh_session_on = False
+
+ NBCommonClient.__init__(self, domain, idlequeue, caller)
+
+
+
+ def connect(self, on_connect, on_connect_failure, proxy, hostname=None, port=5222,
+ on_proxy_failure=None, secure=None):
+ '''
+ Open XMPP connection (open XML streams in both directions).
+ :param hostname: hostname of XMPP server from SRV request
+ :param port: port number of XMPP server
+ :param on_connect: called after stream is successfully opened
+ :param on_connect_failure: called when error occures during connection
+ :param on_proxy_failure: called if error occurres during TCP connection to
+ proxy server or during connection to the proxy
+ :param proxy: dictionary with bosh-related paramters. It should contain at
+ least values for keys 'host' and 'port' - connection details for proxy
+ server and optionally keys 'user' and 'pass' as proxy credentials
+ :param secure: if
+ '''
+ NBCommonClient.connect(self, on_connect, on_connect_failure, hostname, port,
+ on_proxy_failure, proxy, secure)
+
+ if hostname:
+ self.route_host = hostname
+ else:
+ self.route_host = self.Server
+
+ assert(proxy.has_key('type'))
+ assert(proxy['type']=='bosh')
- proxy = kw['proxy']
- #self.bosh_protocol, self.bosh_host, self.bosh_uri = transports_nb.urisplit(proxy['host'])
- self.bosh_port = proxy['port']
self.bosh_wait = proxy['bosh_wait']
self.bosh_hold = proxy['bosh_hold']
- self.bosh_to = proxy['to']
- #self.bosh_ack = proxy['bosh_ack']
- #self.bosh_secure = proxy['bosh_secure']
- NBCommonClient.connect(self, *args, **kw)
+ self.bosh_host = proxy['host']
+ self.bosh_port = proxy['port']
+ self.bosh_content = proxy['bosh_content']
+
+ # _on_tcp_failure is callback for errors which occur during name resolving or
+ # TCP connecting.
+ self._on_tcp_failure = self.on_proxy_failure
+
+
+
+ # in BOSH, client connects to Connection Manager instead of directly to
+ # XMPP server ((hostname, port)). If HTTP Proxy is specified, client connects
+ # to HTTP proxy and Connection Manager is specified at URI and Host header
+ # in HTTP message
+
+ # tcp_host, tcp_port is hostname and port for socket connection - Connection
+ # Manager or HTTP proxy
+ if proxy.has_key('proxy_host') and proxy['proxy_host'] and \
+ proxy.has_key('proxy_port') and proxy['proxy_port']:
+
+ tcp_host=proxy['proxy_host']
+ tcp_port=proxy['proxy_port']
+
+ # user and password for HTTP proxy
+ if proxy.has_key('user') and proxy['user'] and \
+ proxy.has_key('pass') and proxy['pass']:
+
+ proxy_creds=(proxy['user'],proxy['pass'])
+ else:
+ proxy_creds=(None, None)
+
+ else:
+ tcp_host = transports_nb.urisplit(proxy['host'])[1]
+ tcp_port=proxy['port']
+
+ if tcp_host is None:
+ self._on_connect_failure("Invalid BOSH URI")
+ return
+
+ self.socket = self.get_socket()
+
+ self._resolve_hostname(
+ hostname=tcp_host,
+ port=tcp_port,
+ on_success=self._try_next_ip,
+ on_failure=self._on_tcp_failure)
+
+ def _on_stream_start(self):
+ '''
+ Called after XMPP stream is opened. In BOSH, TLS is negotiated on socket
+ connect so success callback can be invoked after TCP connect.
+ (authentication is started from auth() method)
+ '''
+ self.onreceive(None)
+ if self.connected == 'tcp':
+ self._on_connect()
+
+ def get_socket(self):
+ tmp = transports_nb.NonBlockingHTTP(
+ raise_event=self.raise_event,
+ on_disconnect=self.on_http_disconnect,
+ http_uri = self.bosh_host,
+ http_port = self.bosh_port,
+ http_version = self.http_version
+ )
+ tmp.PlugIn(self)
+ return tmp
+
+ def on_http_disconnect(self):
+ log.info('HTTP socket disconnected')
+ #import traceback
+ #traceback.print_stack()
+ if self.bosh_session_on:
+ self.socket.connect(
+ conn_5tuple=self.current_ip,
+ on_connect=self.on_http_reconnect,
+ on_connect_failure=self.on_disconnect)
+ else:
+ self.on_disconnect()
+
+ def on_http_reconnect(self):
+ self.socket._plug_idle()
+ log.info('Connected to BOSH CM again')
+ pass
+
+
+ def on_http_reconnect_fail(self):
+ log.error('Error when reconnecting to BOSH CM')
+ self.on_disconnect()
def send(self, stanza, now = False):
(id, stanza_to_send) = self.Dispatcher.assign_id(stanza)
- self.Connection.send(
+ self.socket.send(
self.boshify_stanza(stanza_to_send),
now = now)
return id
+ def get_rid(self):
+ # does this need a lock??"
+ self.bosh_rid = self.bosh_rid + 1
+ return str(self.bosh_rid)
+
def get_bodytag(self):
# this should be called not until after session creation response so sid has
# to be initialized.
- assert(self.sid is not None)
- self.rid = self.rid+1
+ assert(hasattr(self, 'bosh_sid'))
return protocol.BOSHBody(
- attrs={ 'rid': str(self.bosh_rid),
+ attrs={ 'rid': self.get_rid(),
'sid': self.bosh_sid})
-
- def get_initial_bodytag(self):
- return protocol.BOSHBody(
- attrs={'content': 'text/xml; charset=utf-8',
+ def get_initial_bodytag(self, after_SASL=False):
+ tag = protocol.BOSHBody(
+ attrs={'content': self.bosh_content,
'hold': str(self.bosh_hold),
+ 'route': '%s:%s' % (self.route_host, self.Port),
'to': self.bosh_to,
'wait': str(self.bosh_wait),
- 'rid': str(self.bosh_rid),
+ 'rid': self.get_rid(),
+ 'xml:lang': self.bosh_xml_lang,
'xmpp:version': '1.0',
- 'xmlns:xmpp': 'urn:xmpp:xbosh'}
- )
+ 'ver': '1.6',
+ 'xmlns:xmpp': 'urn:xmpp:xbosh'})
+ if after_SASL:
+ tag.delAttr('content')
+ tag.delAttr('hold')
+ tag.delAttr('route')
+ tag.delAttr('wait')
+ tag.delAttr('ver')
+ # xmpp:restart attribute is essential for stream restart request
+ tag.setAttr('xmpp:restart','true')
+ tag.setAttr('sid',self.bosh_sid)
+
+ return tag
+
def get_closing_bodytag(self):
closing_bodytag = self.get_bodytag()
@@ -82,31 +210,26 @@ class BOSHClient(NBCommonClient):
return closing_bodytag
- def boshify_stanza(self, stanza):
- ''' wraps stanza by body tag or modifies message entirely (in case of stream
- opening and closing'''
- log.info('boshify_staza - type is: %s' % type(stanza))
- if isinstance(stanza, simplexml.Node):
- tag = self.get_bodytag()
- return tag.setPayload(stanza)
- else:
- # only stream initialization and stream terminatoion are not Nodes
- if stanza.startswith(dispatcher_nb.XML_DECLARATION):
- # stream init
- return self.get_initial_bodytag()
- else:
- # should be stream closing
- assert(stanza == dispatcher_nb.STREAM_TERMINATOR)
- return self.get_closing_bodytag()
+ def boshify_stanza(self, stanza=None, body_attrs=None):
+ ''' wraps stanza by body tag with rid and sid '''
+ #log.info('boshify_staza - type is: %s, stanza is %s' % (type(stanza), stanza))
+ tag = self.get_bodytag()
+ tag.setPayload([stanza])
+ return tag
+ def on_bodytag_attrs(self, body_attrs):
+ #log.info('on_bodytag_attrs: %s' % body_attrs)
+ if body_attrs.has_key('type'):
+ if body_attrs['type']=='terminated':
+ # BOSH session terminated
+ self.bosh_session_on = False
+ elif body_attrs['type']=='error':
+ # recoverable error
+ pass
+ if not self.bosh_sid:
+ # initial response - when bosh_sid is set
+ self.bosh_session_on = True
+ self.bosh_sid = body_attrs['sid']
+ self.Dispatcher.Stream._document_attrs['id']=body_attrs['authid']
- def _on_stream_start(self):
- '''
- Called after XMPP stream is opened. In BOSH, TLS is negotiated elsewhere
- so success callback can be invoked.
- (authentication is started from auth() method)
- '''
- self.onreceive(None)
- if self.connected == 'tcp':
- self._on_connect()
diff --git a/src/common/xmpp/client.py b/src/common/xmpp/client.py
index c30905963..f9f200dac 100644
--- a/src/common/xmpp/client.py
+++ b/src/common/xmpp/client.py
@@ -32,7 +32,7 @@ class PlugIn:
def PlugIn(self,owner):
""" Attach to main instance and register ourself and all our staff in it. """
self._owner=owner
- log.debug('Plugging %s into %s'%(self,self._owner))
+ log.info('Plugging %s __INTO__ %s' % (self,self._owner))
if owner.__dict__.has_key(self.__class__.__name__):
log.debug('Plugging ignored: another instance already plugged.')
return
@@ -41,17 +41,27 @@ class PlugIn:
if owner.__dict__.has_key(method.__name__):
self._old_owners_methods.append(owner.__dict__[method.__name__])
owner.__dict__[method.__name__]=method
- owner.__dict__[self.__class__.__name__]=self
+ if self.__class__.__name__.endswith('Dispatcher'):
+ # FIXME: I need BOSHDispatcher or XMPPDispatcher on .Dispatcher
+ # there must be a better way..
+ owner.__dict__['Dispatcher']=self
+ else:
+ owner.__dict__[self.__class__.__name__]=self
+
# following will not work for classes inheriting plugin()
#if self.__class__.__dict__.has_key('plugin'): return self.plugin(owner)
if hasattr(self,'plugin'): return self.plugin(owner)
def PlugOut(self):
""" Unregister all our staff from main instance and detach from it. """
- log.debug('Plugging %s out of %s.'%(self,self._owner))
+ log.info('Plugging %s __OUT__ of %s.' % (self,self._owner))
for method in self._exported_methods: del self._owner.__dict__[method.__name__]
for method in self._old_owners_methods: self._owner.__dict__[method.__name__]=method
- del self._owner.__dict__[self.__class__.__name__]
- if self.__class__.__dict__.has_key('plugout'): return self.plugout()
+ if self.__class__.__name__.endswith('Dispatcher'):
+ del self._owner.__dict__['Dispatcher']
+ else:
+ del self._owner.__dict__[self.__class__.__name__]
+ #if self.__class__.__dict__.has_key('plugout'): return self.plugout()
+ if hasattr(self,'plugout'): return self.plugout()
del self._owner
diff --git a/src/common/xmpp/client_nb.py b/src/common/xmpp/client_nb.py
index df6c4ca20..c21437de5 100644
--- a/src/common/xmpp/client_nb.py
+++ b/src/common/xmpp/client_nb.py
@@ -41,11 +41,10 @@ class NBCommonClient:
:param caller: calling object - it has to implement certain methods (necessary?)
'''
-
self.Namespace = protocol.NS_CLIENT
-
- self.idlequeue = idlequeue
self.defaultNamespace = self.Namespace
+
+ self.idlequeue = idlequeue
self.disconnect_handlers = []
self.Server = domain
@@ -85,12 +84,14 @@ class NBCommonClient:
self.SASL.PlugOut()
if self.__dict__.has_key('NonBlockingTLS'):
self.NonBlockingTLS.PlugOut()
- if self.__dict__.has_key('NBHTTPPROXYsocket'):
+ if self.__dict__.has_key('NBHTTPProxySocket'):
self.NBHTTPPROXYsocket.PlugOut()
- if self.__dict__.has_key('NBSOCKS5PROXYsocket'):
+ if self.__dict__.has_key('NBSOCKS5ProxySocket'):
self.NBSOCKS5PROXYsocket.PlugOut()
- if self.__dict__.has_key('NonBlockingTcp'):
- self.NonBlockingTcp.PlugOut()
+ if self.__dict__.has_key('NonBlockingTCP'):
+ self.NonBlockingTCP.PlugOut()
+ if self.__dict__.has_key('NonBlockingHTTP'):
+ self.NonBlockingHTTP.PlugOut()
def send(self, stanza, now = False):
@@ -106,7 +107,7 @@ class NBCommonClient:
def connect(self, on_connect, on_connect_failure, hostname=None, port=5222,
on_proxy_failure=None, proxy=None, secure=None):
'''
- Open XMPP connection (open streams in both directions).
+ Open XMPP connection (open XML streams in both directions).
:param hostname: hostname of XMPP server from SRV request
:param port: port number of XMPP server
:param on_connect: called after stream is successfully opened
@@ -118,70 +119,14 @@ class NBCommonClient:
optionally keys 'user' and 'pass' as proxy credentials
:param secure:
'''
- self.Port = port
- if hostname:
- xmpp_hostname = hostname
- else:
- xmpp_hostname = self.Server
-
self.on_connect = on_connect
self.on_connect_failure=on_connect_failure
self.on_proxy_failure = on_proxy_failure
self._secure = secure
self.Connection = None
+ self.Port = port
- if proxy:
- # with proxies, client connects to proxy instead of directly to
- # XMPP server ((hostname, port))
- # tcp_server is machine used for socket connection
- tcp_server=proxy['host']
- tcp_port=proxy['port']
- self._on_tcp_failure = self.on_proxy_failure
- if proxy.has_key('type'):
- if proxy.has_key('user') and proxy.has_key('pass'):
- proxy_creds=(proxy['user'],proxy['pass'])
- else:
- proxy_creds=(None, None)
-
- type_ = proxy['type']
- if type_ == 'socks5':
- # SOCKS5 proxy
- self.socket = transports_nb.NBSOCKS5ProxySocket(
- on_disconnect=self.on_disconnect,
- proxy_creds=proxy_creds,
- xmpp_server=(xmpp_hostname, self.Port))
- elif type_ == 'http':
- # HTTP CONNECT to proxy
- self.socket = transports_nb.NBHTTPProxySocket(
- on_disconnect=self.on_disconnect,
- proxy_creds=proxy_creds,
- xmpp_server=(xmpp_hostname, self.Port))
- elif type_ == 'bosh':
- # BOSH - XMPP over HTTP
- tcp_server = transports_nb.urisplit(tcp_server)[1]
- self.socket = transports_nb.NonBlockingHTTP(
- on_disconnect=self.on_disconnect,
- http_uri = proxy['host'],
- http_port = tcp_port)
- else:
- # HTTP CONNECT to proxy from environment variables
- self.socket = transports_nb.NBHTTPProxySocket(
- on_disconnect=self.on_disconnect,
- proxy_creds=(None, None),
- xmpp_server=(xmpp_hostname, self.Port))
- else:
- self._on_tcp_failure = self._on_connect_failure
- tcp_server=xmpp_hostname
- tcp_port=self.Port
- self.socket = transports_nb.NonBlockingTcp(on_disconnect = self.on_disconnect)
- self.socket.PlugIn(self)
-
- self._resolve_hostname(
- hostname=tcp_server,
- port=tcp_port,
- on_success=self._try_next_ip,
- on_failure=self._on_tcp_failure)
@@ -232,13 +177,14 @@ class NBCommonClient:
started, and _on_connect_failure on failure.
'''
#FIXME: use RegisterHandlerOnce instead of onreceive
- log.info('=============xmpp_connect_machine() >> mode: %s, data: %s' % (mode,data))
+ log.info('========xmpp_connect_machine() >> mode: %s, data: %s' % (mode,str(data)[:20] ))
def on_next_receive(mode):
+ log.info('setting %s on next receive' % mode)
if mode is None:
self.onreceive(None)
else:
- self.onreceive(lambda data:self._xmpp_connect_machine(mode, data))
+ self.onreceive(lambda _data:self._xmpp_connect_machine(mode, _data))
if not mode:
dispatcher_nb.Dispatcher().PlugIn(self)
@@ -259,9 +205,11 @@ class NBCommonClient:
if not self.Dispatcher.Stream.features:
on_next_receive('RECEIVE_STREAM_FEATURES')
else:
+ log.info('got STREAM FEATURES in first read')
self._xmpp_connect_machine(mode='STREAM_STARTED')
else:
+ log.info('incoming stream version less than 1.0')
self._xmpp_connect_machine(mode='STREAM_STARTED')
elif mode == 'RECEIVE_STREAM_FEATURES':
@@ -274,6 +222,7 @@ class NBCommonClient:
mode='FAILURE',
data='Missing in 1.0 stream')
else:
+ log.info('got STREAM FEATURES in second read')
self._xmpp_connect_machine(mode='STREAM_STARTED')
elif mode == 'STREAM_STARTED':
@@ -294,6 +243,10 @@ class NBCommonClient:
self.onreceive(None)
self.on_connect(self, self.connected)
+ def raise_event(self, event_type, data):
+ log.info('raising event from transport: %s %s' % (event_type,data))
+ if hasattr(self, 'Dispatcher'):
+ self.Dispatcher.Event('', event_type, data)
# moved from client.CommonClient:
@@ -324,8 +277,6 @@ class NBCommonClient:
def auth(self, user, password, resource = '', sasl = 1, on_auth = None):
-
- print 'auth called'
''' Authenticate connnection and bind resource. If resource is not provided
random one or library name used. '''
self._User, self._Password, self._Resource, self._sasl = user, password, resource, sasl
@@ -388,39 +339,6 @@ class NBCommonClient:
self.on_auth(self, None)
-
-
-class NonBlockingClient(NBCommonClient):
- ''' Example client class, based on CommonClient. '''
-
-
- def _on_stream_start(self):
- '''
- Called after XMPP stream is opened.
- In pure XMPP client, TLS negotiation may follow after esabilishing a stream.
- '''
- self.onreceive(None)
- if self.connected == 'tcp':
- if not self.connected or self._secure is not None and not self._secure:
- # if we are disconnected or TLS/SSL is not desired, return
- self._on_connect()
- return
- if not self.Dispatcher.Stream.features.getTag('starttls'):
- # if server doesn't advertise TLS in init response
- self._on_connect()
- return
- if self.incoming_stream_version() != '1.0':
- self._on_connect()
- return
- # otherwise start TLS
- tls_nb.NonBlockingTLS().PlugIn(
- self,
- on_tls_success=lambda: self._xmpp_connect(socket_type='tls'),
- on_tls_failure=self._on_connect_failure)
- elif self.connected == 'tls':
- self._on_connect()
-
-
def initRoster(self):
''' Plug in the roster. '''
if not self.__dict__.has_key('NonBlockingRoster'):
@@ -440,3 +358,101 @@ class NonBlockingClient(NBCommonClient):
self.send(dispatcher_nb.Presence(to=jid, typ=typ))
+
+class NonBlockingClient(NBCommonClient):
+ ''' Example client class, based on CommonClient. '''
+
+ def __init__(self, domain, idlequeue, caller=None):
+ NBCommonClient.__init__(self, domain, idlequeue, caller)
+
+ def connect(self, on_connect, on_connect_failure, hostname=None, port=5222,
+ on_proxy_failure=None, proxy=None, secure=None):
+
+ NBCommonClient.connect(self, on_connect, on_connect_failure, hostname, port,
+ on_proxy_failure, proxy, secure)
+
+ if hostname:
+ xmpp_hostname = hostname
+ else:
+ xmpp_hostname = self.Server
+
+ if proxy:
+ # with proxies, client connects to proxy instead of directly to
+ # XMPP server ((hostname, port))
+ # tcp_host is machine used for socket connection
+ tcp_host=proxy['host']
+ tcp_port=proxy['port']
+ self._on_tcp_failure = self.on_proxy_failure
+ if proxy.has_key('type'):
+ assert(proxy['type']!='bosh')
+ if proxy.has_key('user') and proxy.has_key('pass'):
+ proxy_creds=(proxy['user'],proxy['pass'])
+ else:
+ proxy_creds=(None, None)
+
+ type_ = proxy['type']
+ if type_ == 'socks5':
+ # SOCKS5 proxy
+ self.socket = transports_nb.NBSOCKS5ProxySocket(
+ on_disconnect=self.on_disconnect,
+ proxy_creds=proxy_creds,
+ xmpp_server=(xmpp_hostname, self.Port))
+ elif type_ == 'http':
+ # HTTP CONNECT to proxy
+ self.socket = transports_nb.NBHTTPProxySocket(
+ on_disconnect=self.on_disconnect,
+ proxy_creds=proxy_creds,
+ xmpp_server=(xmpp_hostname, self.Port))
+ else:
+ # HTTP CONNECT to proxy from environment variables
+ self.socket = transports_nb.NBHTTPProxySocket(
+ on_disconnect=self.on_disconnect,
+ proxy_creds=(None, None),
+ xmpp_server=(xmpp_hostname, self.Port))
+ else:
+ self._on_tcp_failure = self._on_connect_failure
+ tcp_host=xmpp_hostname
+ tcp_port=self.Port
+ self.socket = transports_nb.NonBlockingTCP(
+ raise_event = self.raise_event,
+ on_disconnect = self.on_disconnect)
+
+ self.socket.PlugIn(self)
+
+ self._resolve_hostname(
+ hostname=tcp_host,
+ port=tcp_port,
+ on_success=self._try_next_ip,
+ on_failure=self._on_tcp_failure)
+
+
+
+
+ def _on_stream_start(self):
+ '''
+ Called after XMPP stream is opened.
+ In pure XMPP client, TLS negotiation may follow after esabilishing a stream.
+ '''
+ self.onreceive(None)
+ if self.connected == 'tcp':
+ if not self.connected or not self._secure:
+ # if we are disconnected or TLS/SSL is not desired, return
+ self._on_connect()
+ return
+ if not self.Dispatcher.Stream.features.getTag('starttls'):
+ # if server doesn't advertise TLS in init response
+ self._on_connect()
+ return
+ if self.incoming_stream_version() != '1.0':
+ self._on_connect()
+ return
+ # otherwise start TLS
+ tls_nb.NonBlockingTLS().PlugIn(
+ self,
+ on_tls_success=lambda: self._xmpp_connect(socket_type='tls'),
+ on_tls_failure=self._on_connect_failure)
+ elif self.connected == 'tls':
+ self._on_connect()
+
+
+
diff --git a/src/common/xmpp/dispatcher_nb.py b/src/common/xmpp/dispatcher_nb.py
index 3734d16a9..1c6f04a8b 100644
--- a/src/common/xmpp/dispatcher_nb.py
+++ b/src/common/xmpp/dispatcher_nb.py
@@ -14,7 +14,6 @@
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
-# $Id: dispatcher.py,v 1.40 2006/01/18 19:26:43 normanr Exp $
'''
Main xmpppy mechanism. Provides library with methods to assign different handlers
@@ -30,6 +29,7 @@ from client import PlugIn
import logging
log = logging.getLogger('gajim.c.x.dispatcher_nb')
+log.setLevel(logging.INFO)
# default timeout to wait for response for our id
DEFAULT_TIMEOUT_SECONDS = 25
@@ -38,9 +38,33 @@ ID = 0
STREAM_TERMINATOR = ''
XML_DECLARATION = ''
-class Dispatcher(PlugIn):
+
+
+
+# FIXME: ugly
+from client_nb import NonBlockingClient
+from bosh import BOSHClient
+class Dispatcher():
+# Why is this here - I needed to redefine Dispatcher for BOSH and easiest way
+# was to inherit original Dispatcher (now renamed to XMPPDispatcher). Trouble
+# is that reference used to access dispatcher instance is in Client attribute
+# named by __class__.__name__ of the dispatcher instance .. long story short:
+# I wrote following to avoid changing each client.Dispatcher.whatever() in xmpp/
+
+# If having two kinds of dispatcher will go well, I will rewrite the
+ def PlugIn(self, client_obj, after_SASL=False):
+ if isinstance(client_obj, NonBlockingClient):
+ XMPPDispatcher().PlugIn(client_obj)
+ elif isinstance(client_obj, BOSHClient):
+ BOSHDispatcher().PlugIn(client_obj, after_SASL)
+
+
+
+class XMPPDispatcher(PlugIn):
''' Ancestor of PlugIn class. Handles XMPP stream, i.e. aware of stream headers.
Can be plugged out/in to restart these headers (used for SASL f.e.). '''
+
+
def __init__(self):
PlugIn.__init__(self)
self.handlers={}
@@ -84,8 +108,6 @@ class Dispatcher(PlugIn):
def plugin(self, owner):
''' Plug the Dispatcher instance into Client class instance and send initial stream header. Used internally.'''
- log.debug('Dispatcher plugin')
-
self._init()
self._owner.lastErrNode = None
self._owner.lastErr = None
@@ -106,8 +128,8 @@ class Dispatcher(PlugIn):
def StreamInit(self):
''' Send an initial stream header. '''
self.Stream = simplexml.NodeBuilder()
- self.Stream._dispatch_depth = 2
self.Stream.dispatch = self.dispatch
+ self.Stream._dispatch_depth = 2
self.Stream.stream_header_received = self._check_stream_start
self.Stream.features = None
self._metastream = Node('stream:stream')
@@ -159,7 +181,7 @@ class Dispatcher(PlugIn):
''' Creates internal structures for newly registered namespace.
You can register handlers for this namespace afterwards. By default one namespace
already registered (jabber:client or jabber:component:accept depending on context. '''
- log.info('Registering namespace "%s"' % xmlns)
+ log.debug('Registering namespace "%s"' % xmlns)
self.handlers[xmlns]={}
self.RegisterProtocol('unknown', Protocol, xmlns=xmlns)
self.RegisterProtocol('default', Protocol, xmlns=xmlns)
@@ -169,7 +191,7 @@ class Dispatcher(PlugIn):
Needed to start registering handlers for such stanzas.
Iq, message and presence protocols are registered by default. '''
if not xmlns: xmlns=self._owner.defaultNamespace
- log.info('Registering protocol "%s" as %s(%s)' %(tag_name, Proto, xmlns))
+ log.debug('Registering protocol "%s" as %s(%s)' %(tag_name, Proto, xmlns))
self.handlers[xmlns][tag_name]={type:Proto, 'default':[]}
def RegisterNamespaceHandler(self, xmlns, handler, typ='', ns='', makefirst=0, system=0):
@@ -196,7 +218,7 @@ class Dispatcher(PlugIn):
'''
if not xmlns:
xmlns=self._owner.defaultNamespace
- log.info('Registering handler %s for "%s" type->%s ns->%s(%s)' %
+ log.debug('Registering handler %s for "%s" type->%s ns->%s(%s)' %
(handler, name, typ, ns, xmlns))
if not typ and not ns:
typ='default'
@@ -287,32 +309,18 @@ class Dispatcher(PlugIn):
def dispatch(self, stanza, session=None, direct=0):
''' Main procedure that performs XMPP stanza recognition and calling apppropriate handlers for it.
Called internally. '''
+ #log.info('dispatch called: stanza = %s, session = %s, direct= %s' % (stanza, session, direct))
if not session:
session = self
session.Stream._mini_dom = None
name = stanza.getName()
- if not direct and self._owner._component:
- if name == 'route':
- if stanza.getAttr('error') is 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()
+
+ #log.info('in dispatch, getting ns for %s, and the ns is %s' % (stanza, xmlns))
if not self.handlers.has_key(xmlns):
log.warn("Unknown namespace: " + xmlns)
xmlns='unknown'
@@ -330,7 +338,6 @@ class Dispatcher(PlugIn):
stanza.props=stanza.getProperties()
ID=stanza.getID()
- log.debug("Dispatching %s stanza with type->%s props->%s id->%s"%(name,typ,stanza.props,ID))
list=['default'] # we will use all handlers:
if self.handlers[xmlns][name].has_key(typ): list.append(typ) # from very common...
for prop in stanza.props:
@@ -427,3 +434,56 @@ class Dispatcher(PlugIn):
stanza.setParent(self._metastream)
return (_ID, stanza)
+class BOSHDispatcher(XMPPDispatcher):
+
+ def PlugIn(self, owner, after_SASL=False):
+ self.after_SASL = after_SASL
+ XMPPDispatcher.PlugIn(self, owner)
+
+ def StreamInit(self):
+ ''' Send an initial stream header. '''
+ self.Stream = simplexml.NodeBuilder()
+ self.Stream.dispatch = self.dispatch
+ self.Stream._dispatch_depth = 2
+ self.Stream.stream_header_received = self._check_stream_start
+ self.Stream.features = None
+
+ self._metastream = Node('stream:stream')
+ self._metastream.setNamespace(self._owner.Namespace)
+ self._metastream.setAttr('version', '1.0')
+ self._metastream.setAttr('xmlns:stream', NS_STREAMS)
+ self._metastream.setAttr('to', self._owner.Server)
+ if locale.getdefaultlocale()[0]:
+ self._metastream.setAttr('xml:lang',
+ locale.getdefaultlocale()[0].split('_')[0])
+
+ self.restart = True
+ self._owner.Connection.send(self._owner.get_initial_bodytag(self.after_SASL))
+
+
+ def StreamTerminate(self):
+ ''' Send a stream terminator. '''
+ self._owner.Connection.send(self._owner.get_closing_bodytag())
+
+ def ProcessNonBlocking(self, data=None):
+
+ if self.restart:
+ fromstream = self._metastream
+ fromstream.setAttr('from', fromstream.getAttr('to'))
+ fromstream.delAttr('to')
+ data = '%s%s>%s' % (XML_DECLARATION,str(fromstream)[:-2] ,data)
+ self.restart = False
+
+ return XMPPDispatcher.ProcessNonBlocking(self, data)
+
+ def dispatch(self, stanza, session=None, direct=0):
+ if stanza.getName()=='body' and stanza.getNamespace()==NS_HTTP_BIND:
+ self._owner.on_bodytag_attrs(stanza.getAttrs())
+ #self._owner.send_empty_bodytag()
+ for child in stanza.getChildren():
+ XMPPDispatcher.dispatch(self, child, session, direct)
+ else:
+ XMPPDispatcher.dispatch(self, stanza, session, direct)
+
+
+
diff --git a/src/common/xmpp/simplexml.py b/src/common/xmpp/simplexml.py
index f7561269b..84d5165fa 100644
--- a/src/common/xmpp/simplexml.py
+++ b/src/common/xmpp/simplexml.py
@@ -20,7 +20,7 @@ I'm personally using it in many other separate projects. It is designed to be as
import xml.parsers.expat
import logging
log = logging.getLogger('gajim.c.x.simplexml')
-
+#log.setLevel(logging.DEBUG)
def XMLescape(txt):
"""Returns provided string with symbols & < > " replaced by their respective XML entities."""
@@ -99,7 +99,10 @@ class Node(object):
for a in self.kids:
if not fancy and (len(self.data)-1)>=cnt: s=s+XMLescape(self.data[cnt])
elif (len(self.data)-1)>=cnt: s=s+XMLescape(self.data[cnt].strip())
- s = s + a.__str__(fancy and fancy+1)
+ if isinstance(a, str) or isinstance(a, unicode):
+ s = s + a.__str__()
+ else:
+ s = s + a.__str__(fancy and fancy+1)
cnt=cnt+1
if not fancy and (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt])
elif (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt].strip())
@@ -343,7 +346,7 @@ class NodeBuilder:
attrs[self.namespaces[ns]+attr[sp+1:]]=attrs[attr]
del attrs[attr] #
self._inc_depth()
- log.info("DEPTH -> %i , tag -> %s, attrs -> %s" % (self.__depth, tag, `attrs`))
+ log.info("STARTTAG.. DEPTH -> %i , tag -> %s, attrs -> %s" % (self.__depth, tag, `attrs`))
if self.__depth == self._dispatch_depth:
if not self._mini_dom :
self._mini_dom = Node(tag=tag, attrs=attrs)
diff --git a/src/common/xmpp/transports_nb.py b/src/common/xmpp/transports_nb.py
index 3ee90241d..a4e35656f 100644
--- a/src/common/xmpp/transports_nb.py
+++ b/src/common/xmpp/transports_nb.py
@@ -3,6 +3,7 @@
##
## Copyright (C) 2003-2004 Alexey "Snake" Nezhdanov
## modified by Dimitur Kirov
+## modified by Dimitur Kirov
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@@ -65,10 +66,21 @@ CONNECTED ='CONNECTED'
DISCONNECTING ='DISCONNECTING'
+
+
class NonBlockingTransport(PlugIn):
- def __init__(self, on_disconnect):
+ def __init__(self, raise_event, on_disconnect):
PlugIn.__init__(self)
+ self.raise_event = raise_event
self.on_disconnect = on_disconnect
+ self.on_connect = None
+ self.on_connect_failure = None
+ self.idlequeue = None
+ self.on_receive = None
+ self.server = None
+ self.port = None
+ self.state = DISCONNECTED
+ self._exported_methods=[self.disconnect, self.onreceive]
def plugin(self, owner):
owner.Connection=self
@@ -79,30 +91,72 @@ class NonBlockingTransport(PlugIn):
self._owner.Connection = None
self._owner = None
+ def connect(self, conn_5tuple, on_connect, on_connect_failure):
+ self.on_connect = on_connect
+ self.on_connect_failure = on_connect_failure
+ (self.server, self.port) = conn_5tuple[4][:2]
+ log.info('NonBlocking Connect :: About tot connect to %s:%s' % (self.server, self.port))
-class NonBlockingTcp(PlugIn, IdleObject):
+ def set_state(self, newstate):
+ assert(newstate in [DISCONNECTED, CONNECTING, CONNECTED, DISCONNECTING])
+ if (self.state, newstate) in [(CONNECTING, DISCONNECTING), (DISCONNECTED, DISCONNECTING)]:
+ log.info('strange move: %s -> %s' % (self.state, newstate))
+ self.state = newstate
+
+ def _on_connect(self, data):
+ ''' preceeds call of on_connect callback '''
+ self.set_state(CONNECTED)
+ self.on_connect()
+
+ def _on_connect_failure(self,err_message):
+ ''' preceeds call of on_connect_failure callback '''
+ # In case of error while connecting we need to close socket
+ # but we don't want to call DisconnectHandlers from client,
+ # thus the do_callback=False
+ self.disconnect(do_callback=False)
+ self.on_connect_failure(err_message=err_message)
+
+ def send(self, raw_data, now=False):
+ if self.state not in [CONNECTED, DISCONNECTING]:
+ # FIXME better handling needed
+ log.error('Trying to send %s when transport is %s.' %
+ (raw_data, self.state))
+ return
+
+ def disconnect(self, do_callback=True):
+ self.set_state(DISCONNECTED)
+ if do_callback:
+ # invoke callback given in __init__
+ self.on_disconnect()
+
+ def onreceive(self, recv_handler):
+ ''' Sets the on_receive callback. Do not confuse it with
+ on_receive() method, which is the callback itself.'''
+ if not recv_handler:
+ if hasattr(self._owner, 'Dispatcher'):
+ self.on_receive = self._owner.Dispatcher.ProcessNonBlocking
+ else:
+ self.on_receive = None
+ return
+ log.info('setting onreceive on %s' % recv_handler)
+ self.on_receive = recv_handler
+
+ def tcp_connection_started(self):
+ self.set_state(CONNECTING)
+ # on_connect/on_conn_failure will be called from self.pollin/self.pollout
+
+
+
+class NonBlockingTCP(NonBlockingTransport, IdleObject):
'''
Non-blocking TCP socket wrapper
'''
- def __init__(self, on_disconnect):
+ def __init__(self, raise_event, on_disconnect):
'''
Class constructor.
'''
-
- PlugIn.__init__(self)
- IdleObject.__init__(self)
-
- self.on_disconnect = on_disconnect
-
- self.on_connect = None
- self.on_connect_failure = None
- self.sock = None
- self.idlequeue = None
- self.on_receive = None
- self.DBG_LINE='socket'
- self.state = DISCONNECTED
-
+ NonBlockingTransport.__init__(self, raise_event, on_disconnect)
# writable, readable - keep state of the last pluged flags
# This prevents replug of same object with the same flags
self.writable = True
@@ -122,14 +176,6 @@ class NonBlockingTcp(PlugIn, IdleObject):
self._exported_methods=[self.disconnect, self.onreceive, self.set_send_timeout,
self.set_timeout, self.remove_timeout]
- def plugin(self, owner):
- owner.Connection=self
- self.idlequeue = owner.idlequeue
-
- def plugout(self):
- self._owner.Connection = None
- self._owner = None
-
def get_fd(self):
try:
@@ -147,14 +193,12 @@ class NonBlockingTcp(PlugIn, IdleObject):
:param on_connect_failure: callback called on failure when estabilishing tcp
connection
'''
- self.on_connect = on_connect
- self.on_connect_failure = on_connect_failure
- (self.server, self.port) = conn_5tuple[4][:2]
- log.info('NonBlocking Connect :: About tot connect to %s:%s' % conn_5tuple[4][:2])
+ NonBlockingTransport.connect(self, conn_5tuple, on_connect, on_connect_failure)
+
try:
self._sock = socket.socket(*conn_5tuple[:3])
except socket.error, (errnum, errstr):
- on_connect_failure('NonBlockingTcp: Error while creating socket: %s %s' % (errnum, errstr))
+ self._on_connect_failure('NonBlockingTCP: Error while creating socket: %s %s' % (errnum, errstr))
return
self._send = self._sock.send
@@ -177,9 +221,8 @@ class NonBlockingTcp(PlugIn, IdleObject):
if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK):
# connecting in progress
- self.set_state(CONNECTING)
log.info('After connect. "%s" raised => CONNECTING' % errstr)
- # on_connect/failure will be called from self.pollin/self.pollout
+ self.tcp_connection_started()
return
elif errnum in (0, 10056, errno.EISCONN):
# already connected - this branch is very unlikely, nonblocking connect() will
@@ -195,27 +238,9 @@ class NonBlockingTcp(PlugIn, IdleObject):
(self.server, self.port, errnum, errstr))
def _on_connect(self, data):
- ''' preceeds call of on_connect callback '''
- self.set_state(CONNECTED)
+ ''' with TCP socket, we have to remove send-timeout '''
self.idlequeue.remove_timeout(self.get_fd())
- self.on_connect()
-
-
- def set_state(self, newstate):
- assert(newstate in [DISCONNECTED, CONNECTING, CONNECTED, DISCONNECTING])
- if (self.state, newstate) in [(CONNECTING, DISCONNECTING), (DISCONNECTED, DISCONNECTING)]:
- log.info('strange move: %s -> %s' % (self.state, newstate))
- self.state = newstate
-
-
- def _on_connect_failure(self,err_message):
- ''' preceeds call of on_connect_failure callback '''
- # In case of error while connecting we need to close socket
- # but we don't want to call DisconnectHandlers from client,
- # thus the do_callback=False
- self.disconnect(do_callback=False)
- self.on_connect_failure(err_message=err_message)
-
+ NonBlockingTransport._on_connect(self, data)
def pollin(self):
@@ -250,10 +275,7 @@ class NonBlockingTcp(PlugIn, IdleObject):
self._sock.close()
except socket.error, (errnum, errstr):
log.error('Error disconnecting a socket: %s %s' % (errnum,errstr))
- self.set_state(DISCONNECTED)
- if do_callback:
- # invoke callback given in __init__
- self.on_disconnect()
+ NonBlockingTransport.disconnect(self, do_callback)
def read_timeout(self):
'''
@@ -295,11 +317,7 @@ class NonBlockingTcp(PlugIn, IdleObject):
'''Append raw_data to the queue of messages to be send.
If supplied data is unicode string, encode it to utf-8.
'''
-
- if self.state not in [CONNECTED, DISCONNECTING]:
- log.error('Trying to send %s when transport is %s.' %
- (raw_data, self.state))
- return
+ NonBlockingTransport.send(self, raw_data, now)
r = raw_data
if isinstance(r, unicode):
r = r.encode('utf-8')
@@ -343,31 +361,13 @@ class NonBlockingTcp(PlugIn, IdleObject):
sent_data = self.sendbuff[:send_count]
self.sendbuff = self.sendbuff[send_count:]
self._plug_idle()
- self._raise_event(DATA_SENT, sent_data)
+ self.raise_event(DATA_SENT, sent_data)
except socket.error, e:
log.error('_do_send:', exc_info=True)
traceback.print_exc()
self.disconnect()
- def _raise_event(self, event_type, data):
- if data and data.strip():
- log.info('raising event from transport: %s %s' % (event_type,data))
- if hasattr(self._owner, 'Dispatcher'):
- self._owner.Dispatcher.Event('', event_type, data)
-
- def onreceive(self, recv_handler):
- ''' Sets the on_receive callback. Do not confuse it with
- on_receive() method, which is the callback itself.'''
- if not recv_handler:
- if hasattr(self._owner, 'Dispatcher'):
- self.on_receive = self._owner.Dispatcher.ProcessNonBlocking
- else:
- self.on_receive = None
- return
- log.info('setting onreceive on %s' % recv_handler)
- self.on_receive = recv_handler
-
def _do_receive(self):
''' Reads all pending incoming data. Calls owner's disconnected() method if appropriate.'''
@@ -410,7 +410,7 @@ class NonBlockingTcp(PlugIn, IdleObject):
# pass received data to owner
#self.
if self.on_receive:
- self._raise_event(DATA_RECEIVED, received)
+ self.raise_event(DATA_RECEIVED, received)
self._on_receive(received)
else:
# This should never happen, so we need the debug. (If there is no handler
@@ -418,31 +418,37 @@ class NonBlockingTcp(PlugIn, IdleObject):
log.error('SOCKET Unhandled data received: %s' % received)
self.disconnect()
- def _on_receive(self, data):
- # Overriding this method allows modifying received data before it is passed
- # to owner's callback.
- log.info('About to call on_receive which is %s' % self.on_receive)
+ def _on_receive(self,data):
+ '''Preceeds passing received data to Client class. Gets rid of HTTP headers
+ and checks them.'''
self.on_receive(data)
-class NonBlockingHTTP(NonBlockingTcp):
+
+class NonBlockingHTTP(NonBlockingTCP):
'''
Socket wrapper that cretes HTTP message out of sent data and peels-off
HTTP headers from incoming messages
'''
- def __init__(self, http_uri, http_port, on_disconnect):
+ def __init__(self, raise_event, on_disconnect, http_uri, http_port, http_version=None):
self.http_protocol, self.http_host, self.http_path = urisplit(http_uri)
if self.http_protocol is None:
self.http_protocol = 'http'
if self.http_path == '':
http_path = '/'
self.http_port = http_port
- NonBlockingTcp.__init__(self, on_disconnect)
+ if http_version:
+ self.http_version = http_version
+ else:
+ self.http_version = 'HTTP/1.1'
+ # buffer for partial responses
+ self.recvbuff = ''
+ self.expected_length = 0
+ NonBlockingTCP.__init__(self, raise_event, on_disconnect)
def send(self, raw_data, now=False):
-
- NonBlockingTcp.send(
+ NonBlockingTCP.send(
self,
self.build_http_message(raw_data),
now)
@@ -450,21 +456,43 @@ class NonBlockingHTTP(NonBlockingTcp):
def _on_receive(self,data):
'''Preceeds passing received data to Client class. Gets rid of HTTP headers
and checks them.'''
- statusline, headers, httpbody = self.parse_http_message(data)
- if statusline[1] != '200':
- log.error('HTTP Error: %s %s' % (statusline[1], statusline[2]))
- self.disconnect()
+ if not self.recvbuff:
+ # recvbuff empty - fresh HTTP message was received
+ statusline, headers, self.recvbuff = self.parse_http_message(data)
+ if statusline[1] != '200':
+ log.error('HTTP Error: %s %s' % (statusline[1], statusline[2]))
+ self.disconnect()
+ return
+ self.expected_length = int(headers['Content-Length'])
+ else:
+ #sth in recvbuff - append currently received data to HTTP mess in buffer
+ self.recvbuff = '%s%s' % (self.recvbuff, data)
+
+ if self.expected_length > len(self.recvbuff):
+ # If we haven't received the whole HTTP mess yet, let's end the thread.
+ # It will be finnished from one of following poll calls on plugged socket.
return
+
+ # FIXME the reassembling doesn't work - Connection Manager on jabbim.cz
+ # closes TCP connection before sending announced bytes.. WTF
+
+ # all was received, now call the on_receive callback
+ httpbody = self.recvbuff
+
+ self.recvbuff=''
+ self.expected_length=0
self.on_receive(httpbody)
- def build_http_message(self, httpbody):
+ def build_http_message(self, httpbody, method='POST'):
'''
Builds http message with given body.
Values for headers and status line fields are taken from class variables.
)
'''
- headers = ['POST %s HTTP/1.1' % self.http_path,
+ absolute_uri = '%s://%s:%s%s' % (self.http_protocol, self.http_host,
+ self.http_port, self.http_path)
+ headers = ['%s %s %s' % (method, absolute_uri, self.http_version),
'Host: %s:%s' % (self.http_host, self.http_port),
'Content-Type: text/xml; charset=utf-8',
'Content-Length: %s' % len(str(httpbody)),
@@ -482,7 +510,7 @@ class NonBlockingHTTP(NonBlockingTcp):
)
'''
message = message.replace('\r','')
- (header, httpbody) = message.split('\n\n')
+ (header, httpbody) = message.split('\n\n',1)
header = header.split('\n')
statusline = header[0].split(' ')
header = header[1:]
@@ -494,15 +522,15 @@ class NonBlockingHTTP(NonBlockingTcp):
-class NBProxySocket(NonBlockingTcp):
+class NBProxySocket(NonBlockingTCP):
'''
Interface for proxy socket wrappers - when tunnneling XMPP over proxies,
some connecting process usually has to be done before opening stream.
'''
- def __init__(self, on_disconnect, xmpp_server, proxy_creds=(None,None)):
+ def __init__(self, raise_event, on_disconnect, xmpp_server, proxy_creds=(None,None)):
self.proxy_user, self.proxy_pass = proxy_creds
self.xmpp_server = xmpp_server
- NonBlockingTcp.__init__(self, on_disconnect)
+ NonBlockingTCP.__init__(self, raise_event, on_disconnect)
def connect(self, conn_5tuple, on_connect, on_connect_failure):
@@ -515,7 +543,7 @@ class NBProxySocket(NonBlockingTcp):
self.after_proxy_connect = on_connect
- NonBlockingTcp.connect(self,
+ NonBlockingTCP.connect(self,
conn_5tuple=conn_5tuple,
on_connect =self._on_tcp_connect,
on_connect_failure =on_connect_failure)
@@ -526,7 +554,7 @@ class NBProxySocket(NonBlockingTcp):
class NBHTTPProxySocket(NBProxySocket):
- ''' This class can be used instead of NonBlockingTcp
+ ''' This class can be used instead of NonBlockingTCP
HTTP (CONNECT) proxy connection class. Allows to use HTTP proxies like squid with
(optionally) simple authentication (using login and password).
'''
@@ -588,7 +616,7 @@ class NBSOCKS5ProxySocket(NBProxySocket):
redefines only connect method. Allows to use SOCKS5 proxies with
(optionally) simple authentication (only USERNAME/PASSWORD auth).
'''
- # TODO: replace DEBUG with ordinrar logging, replace on_proxy_failure() with
+ # TODO: replace on_proxy_failure() with
# _on_connect_failure, at the end call _on_connect()
def _on_tcp_connect(self):
@@ -620,13 +648,13 @@ class NBSOCKS5ProxySocket(NBProxySocket):
self.send(to_send)
else:
if reply[1] == '\xff':
- self.DEBUG('Authentification to proxy impossible: no acceptable '
- 'auth method', 'error')
+ log.error('Authentification to proxy impossible: no acceptable '
+ 'auth method')
self._owner.disconnected()
self.on_proxy_failure('Authentification to proxy impossible: no '
'acceptable authentification method')
return
- self.DEBUG('Invalid proxy reply', 'error')
+ log.error('Invalid proxy reply')
self._owner.disconnected()
self.on_proxy_failure('Invalid proxy reply')
return
@@ -635,21 +663,21 @@ class NBSOCKS5ProxySocket(NBProxySocket):
if reply is None:
return
if len(reply) != 2:
- self.DEBUG('Invalid proxy reply', 'error')
+ log.error('Invalid proxy reply')
self._owner.disconnected()
self.on_proxy_failure('Invalid proxy reply')
return
if reply[0] != '\x01':
- self.DEBUG('Invalid proxy reply', 'error')
+ log.error('Invalid proxy reply')
self._owner.disconnected()
self.on_proxy_failure('Invalid proxy reply')
return
if reply[1] != '\x00':
- self.DEBUG('Authentification to proxy failed', 'error')
+ log.error('Authentification to proxy failed')
self._owner.disconnected()
self.on_proxy_failure('Authentification to proxy failed')
return
- self.DEBUG('Authentification successfull. Jabber server contacted.','ok')
+ log.info('Authentification successfull. Jabber server contacted.')
# Request connection
req = "\x05\x01\x00"
# If the given destination address is an IP address, we'll
@@ -675,12 +703,12 @@ class NBSOCKS5ProxySocket(NBProxySocket):
if reply is None:
return
if len(reply) < 10:
- self.DEBUG('Invalid proxy reply', 'error')
+ log.error('Invalid proxy reply')
self._owner.disconnected()
self.on_proxy_failure('Invalid proxy reply')
return
if reply[0] != '\x05':
- self.DEBUG('Invalid proxy reply', 'error')
+ log.error('Invalid proxy reply')
self._owner.disconnected()
self.on_proxy_failure('Invalid proxy reply')
return
@@ -700,7 +728,7 @@ class NBSOCKS5ProxySocket(NBProxySocket):
txt = errors[ord(reply[1])-1]
else:
txt = 'Invalid proxy reply'
- self.DEBUG(txt, 'error')
+ log.error(txt)
self.on_proxy_failure(txt)
return
# Get the bound address/port
@@ -709,7 +737,7 @@ class NBSOCKS5ProxySocket(NBProxySocket):
elif reply[3] == "\x03":
begin, end = 4, 4 + reply[4]
else:
- self.DEBUG('Invalid proxy reply', 'error')
+ log.error('Invalid proxy reply')
self._owner.disconnected()
self.on_proxy_failure('Invalid proxy reply')
return
@@ -717,9 +745,6 @@ class NBSOCKS5ProxySocket(NBProxySocket):
if self.on_connect_proxy:
self.on_connect_proxy()
- def DEBUG(self, text, severity):
- ''' Overwrites DEBUG tag to allow debug output be presented as "CONNECTproxy".'''
- return self._owner.DEBUG(DBG_CONNECT_PROXY, text, severity)