plugin ip: implemented XEP-0279 for external ip retrieval + fixed bad exception handling

This commit is contained in:
Goffi 2015-11-08 14:44:30 +01:00
commit 1a5f1bd144
2 changed files with 44 additions and 13 deletions

View file

@ -28,6 +28,9 @@ from twisted.internet import reactor
from twisted.internet import protocol
from twisted.internet import endpoints
from twisted.internet import error as internet_error
from zope.interface import implements
from wokkel import disco, iwokkel
from twisted.words.protocols.jabber.xmlstream import XMPPHandler
import urlparse
try:
import netifaces
@ -40,9 +43,10 @@ PLUGIN_INFO = {
"name": "IP discovery",
"import_name": "IP",
"type": C.PLUG_TYPE_MISC,
"protocols": ["XEP-0279"],
"recommendations": ["NAT-PORT"],
"main": "IPPlugin",
"handler": "no",
"handler": "yes",
"description": _("""This plugin help to discover our external IP address.""")
}
@ -62,6 +66,7 @@ Do you agree to do this request ?
page = GET_IP_PAGE,
domain = urlparse.urlparse(GET_IP_PAGE).netloc,
app_name = C.APP_NAME)
NS_IP_CHECK = "urn:xmpp:sic:1"
PARAMS = """
<params>
@ -77,7 +82,6 @@ PARAMS = """
class IPPlugin(object):
# TODO: refresh IP if a new connection is detected
# TODO: manage IPv6 when implemented in SàT
# TODO: implement XEP-0279
def __init__(self, host):
log.info(_("plugin IP discovery initialization"))
@ -96,6 +100,9 @@ class IPPlugin(object):
self._external_ip_cache = None
self._local_ip_cache = None
def getHandler(self, profile):
return IPPlugin_handler()
def refreshIP(self):
# FIXME: use a trigger instead ?
self._external_ip_cache = None
@ -174,7 +181,6 @@ class IPPlugin(object):
d.addCallback(gotConnection)
return d
@defer.inlineCallbacks
def getLocalIPs(self, profile):
"""Try do discover local area network IPs
@ -228,13 +234,12 @@ class IPPlugin(object):
try:
ip_tuple = yield self._getIPFromExternal(GET_IP_PAGE)
except Exception as internet_error.DNSLookupError:
except (internet_error.DNSLookupError, internet_error.TimeoutError):
log.warning(u"Can't access Domain Name System")
defer.returnValue(addresses)
self._insertFirst(addresses, ip_tuple.local)
defer.returnValue(addresses)
@defer.inlineCallbacks
def getExternalIP(self, profile):
"""Try to discover external IP
@ -245,20 +250,50 @@ class IPPlugin(object):
if self._external_ip_cache is not None:
defer.returnValue(self._external_ip_cache)
# we first try with NAT-Port
# we first try with XEP-0279
if self.host.hasFeature(NS_IP_CHECK, profile=profile):
log.debug(u"Server IP Check available, we use it to retrieve our IP")
client = self.host.getClient(profile)
iq_elt = client.IQ("get")
iq_elt.addElement((NS_IP_CHECK, 'address'))
result_elt = yield iq_elt.send()
try:
address_elt = result_elt.elements(NS_IP_CHECK, 'address').next()
ip_elt = address_elt.elements(NS_IP_CHECK,'ip').next()
except StopIteration:
log.warning(u"Server returned invalid result on XEP-0279 request, we ignore it")
else:
# FIXME: server IP may not be the same as external IP (server can be on local machine or network)
# IP should be checked to see if we have a local one, and rejected in this case
external_ip = str(ip_elt)
log.debug(u"External IP found: {}".format(external_ip))
self._external_ip_cache = external_ip
defer.returnValue(self._external_ip_cache)
# then with NAT-Port
if self._nat is not None:
nat_ip = yield self._nat.getIP()
if nat_ip is not None:
self._external_ip_cache = nat_ip
defer.returnValue(nat_ip)
# then by requesting external website
# and finally by requesting external website
allow_get_ip = yield self._externalAllowed(profile)
try:
ip = (yield webclient.getPage(GET_IP_PAGE)) if allow_get_ip else None
except internet_error.DNSLookupError:
except (internet_error.DNSLookupError, internet_error.TimeoutError):
log.warning(u"Can't access Domain Name System")
ip = None
else:
self._external_ip_cache = ip
defer.returnValue(ip)
class IPPlugin_handler(XMPPHandler):
implements(iwokkel.IDisco)
def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
return [disco.DiscoFeature(NS_IP_CHECK)]
def getDiscoItems(self, requestor, target, nodeIdentifier=''):
return []