SRV lookup moved from xmpp to connection.py
This commit is contained in:
parent
a7f4391083
commit
6d0bf25adc
|
@ -44,6 +44,19 @@ USE_GPG = GnuPG.USE_GPG
|
||||||
from common import i18n
|
from common import i18n
|
||||||
_ = i18n._
|
_ = i18n._
|
||||||
|
|
||||||
|
# determine which DNS resolution library is available
|
||||||
|
HAVE_DNSPYTHON = False
|
||||||
|
HAVE_PYDNS = False
|
||||||
|
try:
|
||||||
|
import dns.resolver # http://dnspython.org/
|
||||||
|
HAVE_DNSPYTHON = True
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
import DNS # http://pydns.sf.net/
|
||||||
|
HAVE_PYDNS = True
|
||||||
|
except ImportError:
|
||||||
|
gajim.log.debug("Could not load one of the supported DNS libraries (dnspython or pydns). SRV records will not be queried and you may need to set custom hostname/port for some servers to be accessible.")
|
||||||
|
|
||||||
|
|
||||||
STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
|
STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
|
||||||
'invisible']
|
'invisible']
|
||||||
|
@ -1171,7 +1184,7 @@ class Connection:
|
||||||
if msg:
|
if msg:
|
||||||
p.setStatus(msg)
|
p.setStatus(msg)
|
||||||
if signed:
|
if signed:
|
||||||
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
|
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
|
||||||
|
|
||||||
if self.connection:
|
if self.connection:
|
||||||
self.connection.send(p)
|
self.connection.send(p)
|
||||||
|
@ -1205,10 +1218,10 @@ class Connection:
|
||||||
if autojoin_val is None: # not there (it's optional)
|
if autojoin_val is None: # not there (it's optional)
|
||||||
autojoin_val == False
|
autojoin_val == False
|
||||||
bm = { 'name': conf.getAttr('name'),
|
bm = { 'name': conf.getAttr('name'),
|
||||||
'jid': conf.getAttr('jid'),
|
'jid': conf.getAttr('jid'),
|
||||||
'autojoin': autojoin_val,
|
'autojoin': autojoin_val,
|
||||||
'password': conf.getTagData('password'),
|
'password': conf.getTagData('password'),
|
||||||
'nick': conf.getTagData('nick') }
|
'nick': conf.getTagData('nick') }
|
||||||
|
|
||||||
self.bookmarks.append(bm)
|
self.bookmarks.append(bm)
|
||||||
self.dispatch('BOOKMARKS', self.bookmarks)
|
self.dispatch('BOOKMARKS', self.bookmarks)
|
||||||
|
@ -1336,7 +1349,34 @@ class Connection:
|
||||||
p = gajim.config.get_per('accounts', self.name, 'custom_port')
|
p = gajim.config.get_per('accounts', self.name, 'custom_port')
|
||||||
use_srv = False
|
use_srv = False
|
||||||
|
|
||||||
con_type = con.connect((h, p), proxy=proxy, secure=secur, use_srv=use_srv)
|
# SRV resolver
|
||||||
|
if use_srv and (HAVE_DNSPYTHON or HAVE_PYDNS):
|
||||||
|
possible_queries = ['_xmpp-client._tcp.' + h]
|
||||||
|
|
||||||
|
for query in possible_queries:
|
||||||
|
try:
|
||||||
|
if HAVE_DNSPYTHON:
|
||||||
|
answers = [x for x in dns.resolver.query(query, 'SRV')]
|
||||||
|
if answers:
|
||||||
|
h = str(answers[0].target)
|
||||||
|
p = int(answers[0].port)
|
||||||
|
break
|
||||||
|
elif HAVE_PYDNS:
|
||||||
|
# ensure we haven't cached an old configuration
|
||||||
|
DNS.ParseResolvConf()
|
||||||
|
response = DNS.Request().req(query, qtype='SRV')
|
||||||
|
answers = response.answers
|
||||||
|
if len(answers) > 0:
|
||||||
|
# ignore the priority and weight for now
|
||||||
|
_t, _t, p, h = answers[0]['data']
|
||||||
|
del _t
|
||||||
|
p = int(port)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
gajim.log.debug('An error occurred while looking up %s' % query)
|
||||||
|
# end of SRV resolver
|
||||||
|
|
||||||
|
con_type = con.connect((h, p), proxy=proxy, secure=secur)
|
||||||
if not con_type:
|
if not con_type:
|
||||||
gajim.log.debug("Couldn't connect to %s" % self.name)
|
gajim.log.debug("Couldn't connect to %s" % self.name)
|
||||||
if not self.retrycount:
|
if not self.retrycount:
|
||||||
|
|
|
@ -156,11 +156,11 @@ class CommonClient:
|
||||||
if hasattr(self, 'Connection'):
|
if hasattr(self, 'Connection'):
|
||||||
return self.Connection._sock.getsockname()
|
return self.Connection._sock.getsockname()
|
||||||
|
|
||||||
def connect(self,server=None,proxy=None, ssl=None, use_srv=None):
|
def connect(self,server=None,proxy=None, ssl=None):
|
||||||
""" Make a tcp/ip connection, protect it with tls/ssl if possible and start XMPP stream. """
|
""" Make a tcp/ip connection, protect it with tls/ssl if possible and start XMPP stream. """
|
||||||
if not server: server=(self.Server,self.Port)
|
if not server: server=(self.Server,self.Port)
|
||||||
if proxy: connected=transports.HTTPPROXYsocket(proxy,server,use_srv).PlugIn(self)
|
if proxy: connected=transports.HTTPPROXYsocket(proxy,server).PlugIn(self)
|
||||||
else: connected=transports.TCPsocket(server,use_srv).PlugIn(self)
|
else: connected=transports.TCPsocket(server).PlugIn(self)
|
||||||
if not connected: return
|
if not connected: return
|
||||||
self._Server,self._Proxy=server,proxy
|
self._Server,self._Proxy=server,proxy
|
||||||
self.connected='tcp'
|
self.connected='tcp'
|
||||||
|
@ -179,7 +179,7 @@ class CommonClient:
|
||||||
|
|
||||||
class Client(CommonClient):
|
class Client(CommonClient):
|
||||||
""" Example client class, based on CommonClient. """
|
""" Example client class, based on CommonClient. """
|
||||||
def connect(self,server=None,proxy=None,secure=None,use_srv=True):
|
def connect(self,server=None,proxy=None,secure=None):
|
||||||
""" Connect to jabber server. If you want to specify different ip/port to connect to you can
|
""" Connect to jabber server. If you want to specify different ip/port to connect to you can
|
||||||
pass it as tuple as first parameter. If there is HTTP proxy between you and server -
|
pass it as tuple as first parameter. If there is HTTP proxy between you and server -
|
||||||
specify it's address and credentials (if needed) in the second argument
|
specify it's address and credentials (if needed) in the second argument
|
||||||
|
@ -188,7 +188,7 @@ class Client(CommonClient):
|
||||||
If you want to disable tls/ssl support completely, set it to 0
|
If you want to disable tls/ssl support completely, set it to 0
|
||||||
Example: connect(('192.168.5.5',5222),{'host':'proxy.my.net','port':8080,'user':'me','password':'secret'})
|
Example: connect(('192.168.5.5',5222),{'host':'proxy.my.net','port':8080,'user':'me','password':'secret'})
|
||||||
Returns '' (on no connection) or 'tcp' or 'tls', depending on the result."""
|
Returns '' (on no connection) or 'tcp' or 'tls', depending on the result."""
|
||||||
if not CommonClient.connect(self,server,proxy,secure,use_srv) or secure<>None and not secure: return self.connected
|
if not CommonClient.connect(self,server,proxy,secure) or secure<>None and not secure: return self.connected
|
||||||
transports.TLS().PlugIn(self)
|
transports.TLS().PlugIn(self)
|
||||||
if not self.Dispatcher.Stream._document_attrs.has_key('version') or not self.Dispatcher.Stream._document_attrs['version']=='1.0': return self.connected
|
if not self.Dispatcher.Stream._document_attrs.has_key('version') or not self.Dispatcher.Stream._document_attrs['version']=='1.0': return self.connected
|
||||||
while not self.Dispatcher.Stream.features and self.Process(): pass # If we get version 1.0 stream the features tag MUST BE presented
|
while not self.Dispatcher.Stream.features and self.Process(): pass # If we get version 1.0 stream the features tag MUST BE presented
|
||||||
|
|
|
@ -33,19 +33,6 @@ from client import PlugIn
|
||||||
from protocol import *
|
from protocol import *
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# determine which DNS resolution library is available
|
|
||||||
HAVE_DNSPYTHON = False
|
|
||||||
HAVE_PYDNS = False
|
|
||||||
try:
|
|
||||||
import dns.resolver # http://dnspython.org/
|
|
||||||
HAVE_DNSPYTHON = True
|
|
||||||
except ImportError:
|
|
||||||
try:
|
|
||||||
import DNS # http://pydns.sf.net/
|
|
||||||
HAVE_PYDNS = True
|
|
||||||
except ImportError:
|
|
||||||
print >> sys.stderr, "Could not load one of the supported DNS libraries (dnspython or pydns). SRV records will not be queried and you may need to set custom hostname/port for some servers to be accessible."
|
|
||||||
|
|
||||||
DATA_RECEIVED='DATA RECEIVED'
|
DATA_RECEIVED='DATA RECEIVED'
|
||||||
DATA_SENT='DATA SENT'
|
DATA_SENT='DATA SENT'
|
||||||
|
|
||||||
|
@ -61,42 +48,13 @@ class error:
|
||||||
|
|
||||||
class TCPsocket(PlugIn):
|
class TCPsocket(PlugIn):
|
||||||
""" This class defines direct TCP connection method. """
|
""" This class defines direct TCP connection method. """
|
||||||
def __init__(self, server=None, use_srv=True):
|
def __init__(self, server=None):
|
||||||
""" Cache connection point 'server'. 'server' is the tuple of (host, port)
|
""" Cache connection point 'server'. 'server' is the tuple of (host, port)
|
||||||
absolutely the same as standart tcp socket uses. """
|
absolutely the same as standart tcp socket uses. """
|
||||||
PlugIn.__init__(self)
|
PlugIn.__init__(self)
|
||||||
self.DBG_LINE='socket'
|
self.DBG_LINE='socket'
|
||||||
self._exported_methods=[self.send,self.disconnect]
|
self._exported_methods=[self.send,self.disconnect]
|
||||||
|
|
||||||
# SRV resolver
|
|
||||||
if use_srv and (HAVE_DNSPYTHON or HAVE_PYDNS):
|
|
||||||
host, port = server
|
|
||||||
possible_queries = ['_xmpp-client._tcp.' + host]
|
|
||||||
|
|
||||||
for query in possible_queries:
|
|
||||||
try:
|
|
||||||
if HAVE_DNSPYTHON:
|
|
||||||
answers = [x for x in dns.resolver.query(query, 'SRV')]
|
|
||||||
if answers:
|
|
||||||
host = str(answers[0].target)
|
|
||||||
port = int(answers[0].port)
|
|
||||||
break
|
|
||||||
elif HAVE_PYDNS:
|
|
||||||
# ensure we haven't cached an old configuration
|
|
||||||
DNS.ParseResolvConf()
|
|
||||||
response = DNS.Request().req(query, qtype='SRV')
|
|
||||||
answers = response.answers
|
|
||||||
if len(answers) > 0:
|
|
||||||
# ignore the priority and weight for now
|
|
||||||
_, _, port, host = answers[0]['data']
|
|
||||||
del _
|
|
||||||
port = int(port)
|
|
||||||
break
|
|
||||||
except:
|
|
||||||
print >> sys.stderr, 'An error occurred while looking up %s' % query
|
|
||||||
server = (host, port)
|
|
||||||
# end of SRV resolver
|
|
||||||
|
|
||||||
self._server = server
|
self._server = server
|
||||||
|
|
||||||
def plugin(self, owner):
|
def plugin(self, owner):
|
||||||
|
@ -189,12 +147,12 @@ class HTTPPROXYsocket(TCPsocket):
|
||||||
""" HTTP (CONNECT) proxy connection class. Uses TCPsocket as the base class
|
""" HTTP (CONNECT) proxy connection class. Uses TCPsocket as the base class
|
||||||
redefines only connect method. Allows to use HTTP proxies like squid with
|
redefines only connect method. Allows to use HTTP proxies like squid with
|
||||||
(optionally) simple authentication (using login and password). """
|
(optionally) simple authentication (using login and password). """
|
||||||
def __init__(self,proxy,server,use_srv=True):
|
def __init__(self,proxy,server):
|
||||||
""" Caches proxy and target addresses.
|
""" Caches proxy and target addresses.
|
||||||
'proxy' argument is a dictionary with mandatory keys 'host' and 'port' (proxy address)
|
'proxy' argument is a dictionary with mandatory keys 'host' and 'port' (proxy address)
|
||||||
and optional keys 'user' and 'password' to use for authentication.
|
and optional keys 'user' and 'password' to use for authentication.
|
||||||
'server' argument is a tuple of host and port - just like TCPsocket uses. """
|
'server' argument is a tuple of host and port - just like TCPsocket uses. """
|
||||||
TCPsocket.__init__(self,server,use_srv)
|
TCPsocket.__init__(self,server)
|
||||||
self.DBG_LINE=DBG_CONNECT_PROXY
|
self.DBG_LINE=DBG_CONNECT_PROXY
|
||||||
self._proxy=proxy
|
self._proxy=proxy
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue