peerlink/peerlink/nodes.py

96 lines
2.3 KiB
Python

# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from threading import Thread
from queue import Queue
from tornado.ioloop import PeriodicCallback
from . import directory
from .localnodes import LocalNodes
from .link import can_connect, node_url
import logging
logger = logging.getLogger('lookup')
class Nodes(Thread):
_active = True
_local = None
_nodes = {}
def __init__(self):
self._local = LocalNodes()
Thread.__init__(self)
self._q = Queue()
self.daemon = True
self._cleanup = PeriodicCallback(lambda: self._q.put(''), 120000)
self._cleanup.start()
self.start()
def cleanup(self):
if self._active:
self._local.cleanup()
for id in list(self._nodes.keys()):
if id in self._local._nodes:
del self._nodes[id]
if not can_connect(self._nodes[id]):
del self._nodes[id]
if not self._active:
break
def fingerprint(self, id):
node = self.get(id)
if node:
return node['cert']
return None
def get(self, id):
# check local nodes
node = self._local.get(id)
if not node:
# check local cache
node = self._nodes.get(id)
# lookup directory
if not node:
try:
node = directory.get(id)
except:
logger.debug('directory failed', exc_info=1)
node = None
if node:
self._nodes[id] = node
if node:
node['url'] = node_url(node)
return node
def info(self):
l = self._local.info()
return {
'local': l,
'nodes': sorted(set(list(self._nodes.keys()) + l))
}
def join(self):
self._active = False
self._q.put('')
self._local.join()
return Thread.join(self)
def run(self):
while self._active:
self._q.get()
if self._active:
self.cleanup()
def url(self, user_id):
node = self.get(user_id)
if node:
url = node['url']
else:
url = None
logger.debug('resolved %s -> %s', user_id, url)
return url