2015-08-20 17:27:15 +02:00
|
|
|
import binascii
|
2016-11-03 20:42:45 +01:00
|
|
|
import logging
|
|
|
|
|
2018-02-20 19:30:56 +01:00
|
|
|
from twisted.internet import defer
|
2018-11-07 21:15:05 +01:00
|
|
|
from lbrynet import conf
|
2015-08-20 17:27:15 +02:00
|
|
|
|
2016-11-03 20:42:45 +01:00
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2018-07-22 00:34:59 +02:00
|
|
|
class DummyPeerFinder:
|
2018-02-15 22:49:00 +01:00
|
|
|
"""This class finds peers which have announced to the DHT that they have certain blobs"""
|
|
|
|
|
2018-05-23 22:48:47 +02:00
|
|
|
def find_peers_for_blob(self, blob_hash, timeout=None, filter_self=True):
|
2018-02-15 22:49:00 +01:00
|
|
|
return defer.succeed([])
|
|
|
|
|
|
|
|
|
|
|
|
class DHTPeerFinder(DummyPeerFinder):
|
2015-08-20 17:27:15 +02:00
|
|
|
"""This class finds peers which have announced to the DHT that they have certain blobs"""
|
2018-07-03 06:51:25 +02:00
|
|
|
#implements(IPeerFinder)
|
2015-08-20 17:27:15 +02:00
|
|
|
|
2018-10-30 18:41:38 +01:00
|
|
|
def __init__(self, component_manager):
|
2017-10-27 19:31:42 +02:00
|
|
|
"""
|
2018-10-30 18:41:38 +01:00
|
|
|
component_manager - an instance of ComponentManager
|
2017-10-27 19:31:42 +02:00
|
|
|
"""
|
2018-10-30 18:41:38 +01:00
|
|
|
self.component_manager = component_manager
|
|
|
|
self.peer_manager = component_manager.peer_manager
|
2018-07-06 02:38:52 +02:00
|
|
|
self.peers = {}
|
2018-10-04 20:39:12 +02:00
|
|
|
self._ongoing_searchs = {}
|
2015-08-20 17:27:15 +02:00
|
|
|
|
2018-05-23 22:48:47 +02:00
|
|
|
def find_peers_for_blob(self, blob_hash, timeout=None, filter_self=True):
|
2017-10-27 19:31:42 +02:00
|
|
|
"""
|
|
|
|
Find peers for blob in the DHT
|
|
|
|
blob_hash (str): blob hash to look for
|
|
|
|
timeout (int): seconds to timeout after
|
|
|
|
filter_self (bool): if True, and if a peer for a blob is itself, filter it
|
|
|
|
from the result
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
list of peers for the blob
|
|
|
|
"""
|
2018-10-30 18:41:38 +01:00
|
|
|
if "dht" in self.component_manager.skip_components:
|
|
|
|
return defer.succeed([])
|
|
|
|
if not self.component_manager.all_components_running("dht"):
|
|
|
|
return defer.succeed([])
|
|
|
|
dht_node = self.component_manager.get_component("dht")
|
|
|
|
|
|
|
|
self.peers.setdefault(blob_hash, {(dht_node.externalIP, dht_node.peerPort,)})
|
2018-10-10 18:25:44 +02:00
|
|
|
if not blob_hash in self._ongoing_searchs or self._ongoing_searchs[blob_hash].called:
|
2018-10-30 18:41:38 +01:00
|
|
|
self._ongoing_searchs[blob_hash] = self._execute_peer_search(dht_node, blob_hash, timeout)
|
|
|
|
|
|
|
|
def _filter_self(blob_hash):
|
|
|
|
my_host, my_port = dht_node.externalIP, dht_node.peerPort
|
|
|
|
return {(host, port) for host, port in self.peers[blob_hash] if (host, port) != (my_host, my_port)}
|
|
|
|
|
|
|
|
peers = set(_filter_self(blob_hash) if filter_self else self.peers[blob_hash])
|
2018-10-04 20:39:12 +02:00
|
|
|
return defer.succeed([self.peer_manager.get_peer(*peer) for peer in peers])
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
2018-10-30 18:41:38 +01:00
|
|
|
def _execute_peer_search(self, dht_node, blob_hash, timeout):
|
2018-10-10 18:25:44 +02:00
|
|
|
bin_hash = binascii.unhexlify(blob_hash)
|
2018-10-30 18:41:38 +01:00
|
|
|
finished_deferred = dht_node.iterativeFindValue(bin_hash, exclude=self.peers[blob_hash])
|
2018-10-10 18:25:44 +02:00
|
|
|
timeout = timeout or conf.settings['peer_search_timeout']
|
|
|
|
if timeout:
|
2018-10-30 18:41:38 +01:00
|
|
|
finished_deferred.addTimeout(timeout, dht_node.clock)
|
2017-10-11 20:05:03 +02:00
|
|
|
try:
|
|
|
|
peer_list = yield finished_deferred
|
2018-10-18 12:42:45 +02:00
|
|
|
self.peers[blob_hash].update({(host, port) for _, host, port in peer_list})
|
2018-05-23 22:48:47 +02:00
|
|
|
except defer.TimeoutError:
|
2018-10-04 20:39:12 +02:00
|
|
|
log.debug("DHT timed out while looking peers for blob %s after %s seconds", blob_hash, timeout)
|
|
|
|
finally:
|
|
|
|
del self._ongoing_searchs[blob_hash]
|