| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- # a very simple (and silly) mechanism for getting the host_ip
- import socket
- from BTL.platform import bttime
- from BTL.obsoletepythonsupport import set
- from BTL.reactor_magic import reactor
- from BTL import defer
- import BTL.stackthreading as threading
- from twisted.internet.protocol import ClientFactory, Protocol
- from twisted.protocols.policies import TimeoutMixin
- try:
- from BTL.iphelp import get_route_ip
- except:
- get_route_ip = None
-
- import thread
- _host_ip = 'unknown'
- _host_ip_callbacks = []
- _host_ip_cachetime = 0
- _host_ips = None
- _host_ips_cachetime = 0
- _thread_running = False
- CACHE_TIME = 3600 # hour
- wrap_task = reactor.callFromThread
- class RecorderProtocol(TimeoutMixin, Protocol):
- def makeConnection(self, transport):
- self.setTimeout(20)
- Protocol.makeConnection(self, transport)
- def connectionMade(self):
- _got_result(self.transport.getHost().host)
- self.transport.write("GET /myip HTTP/1.0\r\n\r\n")
- self.transport.loseConnection()
- def connectionLost(self, reason):
- _got_result(None)
- class RecorderFactory(ClientFactory):
-
- def clientConnectionFailed(self, connector, reason):
- _got_result(None)
- def _resolve():
- try:
- ip = socket.gethostbyname(socket.gethostname())
- except socket.error, e:
- ip = 'unknown'
- reactor.callFromThread(_got_result, ip)
- def _finish(ip):
- global _thread_running
- _thread_running = False
- _got_result(ip)
- def _got_result(ip):
- global _host_ip
- global _host_ip_callbacks
- global _host_ip_cachetime
- global _thread_running
- if hasattr(reactor, 'ident'):
- assert reactor.ident == thread.get_ident()
- if _thread_running:
- return
- if ip is None:
- t = threading.Thread(target=_resolve)
- t.setDaemon(True)
- _thread_running = True
- t.start()
- return
- if ip is not 'unknown':
- _host_ip = ip
- _host_ip_cachetime = bttime()
-
- l = _host_ip_callbacks
- _host_ip_callbacks = []
- for df in l:
- df.callback(_host_ip)
- def get_deferred_host_ip():
- global _host_ip
- global _host_ip_callbacks
- global _host_ip_cachetime
- if hasattr(reactor, 'ident'):
- assert reactor.ident == thread.get_ident()
- if _host_ip is not 'unknown' and _host_ip_cachetime + CACHE_TIME > bttime():
- return defer.succeed(_host_ip)
- if get_route_ip:
- ip = get_route_ip()
- if ip:
- _host_ip = ip
- _host_ip_cachetime = bttime()
- return defer.succeed(_host_ip)
- df = defer.Deferred()
-
- if not _host_ip_callbacks:
- def connect(ip):
- factory = RecorderFactory()
- factory.protocol = RecorderProtocol
- if hasattr(reactor, 'limiter'):
- reactor.connectTCP(ip, 80, factory, urgent=True)
- else:
- reactor.connectTCP(ip, 80, factory)
- rdf = reactor.resolve("ip.bittorrent.com")
- rdf.addCallback(connect)
- rdf.addErrback(lambda e : _got_result(None))
-
- _host_ip_callbacks.append(df)
- return df
- def get_host_ip():
- """ Blocking version, do not use from reactor thread! """
- global _host_ip
- global _host_ip_callbacks
- global _host_ip_cachetime
- if hasattr(reactor, 'ident'):
- assert reactor.ident != thread.get_ident()
- if _host_ip is not 'unknown' and _host_ip_cachetime + CACHE_TIME > bttime():
- return _host_ip
- if get_route_ip:
- ip = get_route_ip()
- if ip:
- _host_ip = ip
- _host_ip_cachetime = bttime()
- return _host_ip
- try:
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.settimeout(5)
-
- # what moron decided to make try/except/finally not work?
- # Guido van Rossum.
- try:
- s.connect(("ip.bittorrent.com", 80))
- endpoint = s.getsockname()
- _host_ip = endpoint[0]
- _host_ip_cachetime = bttime()
- s.send("GET /myip HTTP/1.0\r\n\r\n")
- except (socket.error, socket.timeout), e:
- try:
- _host_ip = socket.gethostbyname(socket.gethostname())
- except socket.error, e:
- pass
- try:
- s.close()
- except:
- pass
- except:
- pass
-
- return _host_ip
- def get_deferred_host_ips():
- global _host_ips
- global _host_ips_cachetime
- if hasattr(reactor, 'ident'):
- assert reactor.ident == thread.get_ident()
- if _host_ips is not None and _host_ips_cachetime + CACHE_TIME > bttime():
- return defer.succeed(_host_ips)
- df = get_deferred_host_ip()
- finaldf = defer.Deferred()
- df.addCallback(_get_deferred_host_ips2, finaldf)
- return finaldf
- def _get_deferred_host_ips2(host_ip, finaldf):
- if hasattr(reactor, 'ident'):
- assert reactor.ident == thread.get_ident()
- df = defer.ThreadedDeferred(wrap_task, _get_deferred_host_ips3,
- host_ip, daemon=True)
- df.chainDeferred(finaldf)
- def _get_deferred_host_ips3(host_ip):
- global _host_ips
- global _host_ips_cachetime
- if hasattr(reactor, 'ident'):
- assert reactor.ident != thread.get_ident()
-
- l = set()
- if host_ip is not 'unknown':
- l.add(host_ip)
- try:
- hostname = socket.gethostname()
- hostname, aliaslist, ipaddrlist = socket.gethostbyname_ex(hostname)
- l.update(ipaddrlist)
- except socket.error, e:
- print "ARG", e
- _host_ips = l
- _host_ips_cachetime = bttime()
- return _host_ips
- def get_host_ips():
- return _get_deferred_host_ips3(get_host_ip())
|