comparison src/plugins/plugin_misc_ip.py @ 1555:eb8aae35085b

plugin ip: local ip cache + DNS error detection
author Goffi <goffi@goffi.org>
date Mon, 02 Nov 2015 22:02:41 +0100
parents 6fa9e8c02c34
children ec3848916ee8
comparison
equal deleted inserted replaced
1554:e281ed2c21db 1555:eb8aae35085b
25 from twisted.web import client as webclient 25 from twisted.web import client as webclient
26 from twisted.internet import defer 26 from twisted.internet import defer
27 from twisted.internet import reactor 27 from twisted.internet import reactor
28 from twisted.internet import protocol 28 from twisted.internet import protocol
29 from twisted.internet import endpoints 29 from twisted.internet import endpoints
30 from twisted.internet import error as internet_error
30 import urlparse 31 import urlparse
31 try: 32 try:
32 import netifaces 33 import netifaces
33 except ImportError: 34 except ImportError:
34 log.warning(u"netifaces is not available, it help discovering IPs, you can install it on https://pypi.python.org/pypi/netifaces") 35 log.warning(u"netifaces is not available, it help discovering IPs, you can install it on https://pypi.python.org/pypi/netifaces")
90 log.debug(u"NAT port plugin not available") 91 log.debug(u"NAT port plugin not available")
91 self._nat = None 92 self._nat = None
92 93
93 # XXX: cache is kept until SàT is restarted 94 # XXX: cache is kept until SàT is restarted
94 # if IP may have changed, use self.refreshIP 95 # if IP may have changed, use self.refreshIP
95 self._ip_cache = None 96 self._external_ip_cache = None
97 self._local_ip_cache = None
96 98
97 def refreshIP(self): 99 def refreshIP(self):
98 # FIXME: use a trigger instead ? 100 # FIXME: use a trigger instead ?
99 self._ip_cache = None 101 self._external_ip_cache = None
102 self._local_ip_cache = None
100 103
101 def _externalAllowed(self, profile): 104 def _externalAllowed(self, profile):
102 """Return value of parameter with autorisation of user to do external requests 105 """Return value of parameter with autorisation of user to do external requests
103 106
104 if parameter is not set, a dialog is shown to use to get its confirmation, and parameted is set according to answer 107 if parameter is not set, a dialog is shown to use to get its confirmation, and parameted is set according to answer
110 if allow_get_ip is None: 113 if allow_get_ip is None:
111 # we don't have autorisation from user yet to use get_ip, we ask him 114 # we don't have autorisation from user yet to use get_ip, we ask him
112 def setParam(allowed): 115 def setParam(allowed):
113 # FIXME: we need to use boolConst as setParam only manage str/unicode 116 # FIXME: we need to use boolConst as setParam only manage str/unicode
114 # need to be fixed when params will be refactored 117 # need to be fixed when params will be refactored
115 self.host.memory.setParam(GET_IP_NAME, C.boolConst(allow_get_ip), GET_IP_CATEGORY) 118 self.host.memory.setParam(GET_IP_NAME, C.boolConst(allowed), GET_IP_CATEGORY)
116 return allowed 119 return allowed
117 d = xml_tools.deferConfirm(self.host, _(GET_IP_CONFIRM), _(GET_IP_CONFIRM_TITLE), profile=profile) 120 d = xml_tools.deferConfirm(self.host, _(GET_IP_CONFIRM), _(GET_IP_CONFIRM_TITLE), profile=profile)
118 d.addCallback(setParam) 121 d.addCallback(setParam)
119 return d 122 return d
120 123
144 147
145 def _getIPFromExternal(self, ext_url): 148 def _getIPFromExternal(self, ext_url):
146 """Get local IP by doing a connection on an external url 149 """Get local IP by doing a connection on an external url
147 150
148 @param ext_utl(str): url to connect to 151 @param ext_utl(str): url to connect to
149 @return (defer.Deferred): return local IP 152 @return (D(str)): return local IP
150 """ 153 """
151 url = urlparse.urlparse(ext_url) 154 url = urlparse.urlparse(ext_url)
152 port = url.port 155 port = url.port
153 if port is None: 156 if port is None:
154 if url.scheme=='http': 157 if url.scheme=='http':
180 @return (deferred): list of lan IP addresses 183 @return (deferred): list of lan IP addresses
181 or empty list if it can't be discovered 184 or empty list if it can't be discovered
182 if there are several addresses, the one used with the server is put first 185 if there are several addresses, the one used with the server is put first
183 """ 186 """
184 # TODO: manage permission requesting (e.g. for UMTS link) 187 # TODO: manage permission requesting (e.g. for UMTS link)
188 if self._local_ip_cache is not None:
189 defer.returnValue(self._local_ip_cache)
185 client = self.host.getClient(profile) 190 client = self.host.getClient(profile)
186 addresses = [] 191 addresses = []
187 192
188 # we first try our luck with netifaces 193 # we first try our luck with netifaces
189 if netifaces is not None: 194 if netifaces is not None:
219 allow_get_ip = yield self._externalAllowed(profile) 224 allow_get_ip = yield self._externalAllowed(profile)
220 225
221 if not allow_get_ip: 226 if not allow_get_ip:
222 defer.returnValue(addresses) 227 defer.returnValue(addresses)
223 228
224 ip_tuple = yield self._getIPFromExternal(GET_IP_PAGE) 229 try:
230 ip_tuple = yield self._getIPFromExternal(GET_IP_PAGE)
231 except Exception as internet_error.DNSLookupError:
232 log.warning(u"Can't access Domain Name System")
233 defer.returnValue(addresses)
225 self._insertFirst(addresses, ip_tuple.local) 234 self._insertFirst(addresses, ip_tuple.local)
226 defer.returnValue(addresses) 235 defer.returnValue(addresses)
227 236
228 237
229 @defer.inlineCallbacks 238 @defer.inlineCallbacks
231 """Try to discover external IP 240 """Try to discover external IP
232 241
233 @param profile: %(doc_profile)s 242 @param profile: %(doc_profile)s
234 @return (deferred): external IP address or None if it can't be discovered 243 @return (deferred): external IP address or None if it can't be discovered
235 """ 244 """
236 if self._ip_cache is not None: 245 if self._external_ip_cache is not None:
237 defer.returnValue(self._ip_cache) 246 defer.returnValue(self._external_ip_cache)
238 247
239 # we first try with NAT-Port 248 # we first try with NAT-Port
240 if self._nat is not None: 249 if self._nat is not None:
241 nat_ip = yield self._nat.getIP() 250 nat_ip = yield self._nat.getIP()
242 if nat_ip is not None: 251 if nat_ip is not None:
252 self._external_ip_cache = nat_ip
243 defer.returnValue(nat_ip) 253 defer.returnValue(nat_ip)
244 254
245 # then by requesting external website 255 # then by requesting external website
246 allow_get_ip = yield self._externalAllowed(profile) 256 allow_get_ip = yield self._externalAllowed(profile)
247 ip = webclient.getPage(GET_IP_PAGE) if allow_get_ip else None 257 try:
258 ip = (yield webclient.getPage(GET_IP_PAGE)) if allow_get_ip else None
259 except internet_error.DNSLookupError:
260 log.warning(u"Can't access Domain Name System")
261 ip = None
262 else:
263 self._external_ip_cache = ip
248 defer.returnValue(ip) 264 defer.returnValue(ip)