示例#1
0
 def rpc_find_node(self, sender, public_key, nodeid, key):
     log.info("finding neighbors of %i in local table",
              int(nodeid.hex(), 16))
     source = Node(nodeid, sender[0], sender[1], public_key=public_key)
     self.welcomeIfNewNode(source)
     node = Node(key)
     neighbors = self.router.findNeighbors(node, exclude=source)
     return list(map(tuple, neighbors))
示例#2
0
 def rpc_find_value(self, sender, public_key, nodeid, key):
     source = Node(nodeid, sender[0], sender[1], public_key=public_key)
     self.welcomeIfNewNode(source)
     value = self.storage.get(key, None)
     if value is None:
         return self.rpc_find_node(sender, public_key, nodeid, key)
     return {'value': value}
示例#3
0
 def getNodeList(self):
     """
     Get the node list in the response.  If there's no value, this should
     be set.
     """
     nodelist = self.response[1] or []
     return [Node(*nodeple) for nodeple in nodelist]
示例#4
0
 def setUp(self):
     self.loop = asyncio.new_event_loop()
     asyncio.set_event_loop(self.loop)
     self.a = genkeys(
         '06391888e37a48cef1ded85a375490df4f9b2c74f7723e88c954a055f3d2685a')
     self.b = genkeys(
         '91f7021a9e8c65ca873747ae24de08e0a7acf58159a8aa6548910fe152dab3d8')
     self.evil = genkeys(
         'c5cb6d3ac7d644df8c72b613d57e4c47df6107989e584863b86bde47df704464')
     self.off = genkeys(
         '8ddaf072b9108444e189773e2ddcb4cbd2a76bbf3db448e55d0bfc131409a197')
     self.a_net = Network(sk=self.a['sk'],
                          network_port=13321,
                          keyname='a',
                          wipe_certs=True,
                          loop=self.loop,
                          daemon=DaemonMock())
     self.b_net = Network(sk=self.b['sk'],
                          network_port=14321,
                          keyname='b',
                          wipe_certs=True,
                          loop=self.loop,
                          daemon=DaemonMock())
     self.evil_net = Network(sk=self.evil['sk'],
                             network_port=15321,
                             keyname='evil',
                             wipe_certs=True,
                             loop=self.loop,
                             daemon=DaemonMock())
     self.off_node = Node(digest(self.off['vk']),
                          ip='127.0.0.1',
                          port=16321,
                          public_key=self.off['curve_key'])
示例#5
0
 def rpc_store(self, sender, public_key, nodeid, key, value):
     source = Node(nodeid, sender[0], sender[1], public_key=public_key)
     self.welcomeIfNewNode(source)
     log.debug("got a store request from %s, storing '%s'='%s'", sender,
               key.hex(), value)
     self.storage[key] = value
     return True
示例#6
0
 def __init__(self, ksize=20, alpha=3, node_id=None, discovery_mode='neighborhood', loop=None, max_peers=64, network_port=None, public_ip=None, event_sock=None, *args, **kwargs):
     """
     Create a server instance.  This will start listening on the given port.
     Args:
         ksize (int): The k parameter from the paper
         alpha (int): The ALPHA parameter from the paper
         node_id: The id for this node on the network.
     """
     self.loop = loop if loop else asyncio.get_event_loop()
     asyncio.set_event_loop(self.loop)
     self.vkcache = {}
     self.ksize = ksize
     self.alpha = alpha
     self.transport = None
     self.protocol = None
     self.refresh_loop = None
     self.save_state_loop = None
     self.event_sock = event_sock
     self.max_peers = max_peers
     self.network_port = network_port
     self.heartbeat_port = self.network_port+HEARTBEAT_PORT_OFFSET
     self.ironhouse = Ironhouse(auth_port=self.network_port+AUTH_PORT_OFFSET, *args, **kwargs)
     self.node = Node(
         node_id=digest(self.ironhouse.vk),
         public_key=self.ironhouse.public_key,
         ip=public_ip or os.getenv('HOST_IP', '127.0.0.1'),
         port=self.network_port
     )
     self.setup_stethoscope()
     self.ironhouse.setup_secure_server()
     self.listen()
     self.saveStateRegularly('state.tmp')
示例#7
0
    async def _lookup_ip(self, cmd, url, vk, *args, **kwargs):
        ip, node = None, None
        try:
            node, cached = await self.dht.network.lookup_ip(vk)
            # NOTE while secure, this is a more loose connection policy
            self.log.fatal('{} resolves for {}'.format(os.getenv('HOST_IP'),
                                                       node))
            if node and not cached:
                ip = node.ip if type(node) == Node else node.split(':')[0]
                public_key = self.dht.network.ironhouse.vk2pk(vk)
                authorization = await self.dht.network.ironhouse.authenticate(
                    public_key, ip)
                self.log.fatal('{} -> {} is {}'.format(os.getenv('HOST_IP'),
                                                       node, authorization))
                if authorization != 'authorized':
                    node = None
                else:
                    n = Node(node_id=digest(vk),
                             public_key=public_key,
                             ip=ip,
                             port=self.dht.network.network_port)
                    self.dht.network.protocol.router.addContact(n)
                    self.dht.network.connect_to_neighbor(n)

                self.log.fatal([
                    item[0]
                    for item in self.dht.network.bootstrappableNeighbors()
                ])
        except Exception as e:
            delim_line = '!' * 64
            err_msg = '\n\n' + delim_line + '\n' + delim_line
            err_msg += '\n ERROR CAUGHT IN LOOKUP FUNCTION {}\ncalled \w args={}\nand kwargs={}\n'\
                        .format(args, kwargs)
            err_msg += '\nError Message: '
            err_msg += '\n\n{}'.format(traceback.format_exc())
            err_msg += '\n' + delim_line + '\n' + delim_line
            self.log.error(err_msg)

        if node is None:

            kwargs = cmd.kwargs
            callback = ReactorCommand.create_callback(
                callback=StateInput.LOOKUP_FAILED, **kwargs)
            self.log.debug(
                "Sending callback failure to mainthread {}".format(callback))
            self.socket.send(callback.serialize())
            # TODO -- send callback to SM saying hey i couldnt lookup this vk

            return

        # Send interpolated command back through pipeline
        ip = node.ip if type(node) == Node else node
        new_url = IPUtils.interpolate_url(url, ip)
        kwargs = cmd.kwargs
        kwargs['url'] = new_url
        new_cmd = ReactorCommand.create_cmd(envelope=cmd.envelope, **kwargs)

        self._execute_cmd(new_cmd)
示例#8
0
 async def bootstrap_node(self, addr):
     result = await self.protocol.ping(addr, self.node.public_key, self.node.id)
     if result[0]:
         node_id, public_key = result[1]
         node = Node(node_id, ip=addr[0], port=addr[1], public_key=public_key)
         authorized = await self.authenticate(node)
         if authorized == True:
             return node
     return None
示例#9
0
def mknode(node_id=None, ip=None, port=None, intid=None):
    """
    Make a node.  Created a random id if not specified.
    """
    if intid is not None:
        node_id = pack('>l', intid)
    if not node_id:
        randbits = str(random.getrandbits(255))
        node_id = hashlib.sha1(randbits.encode()).digest()
    return Node(node_id, ip, port)
示例#10
0
    async def _refresh_table(self):
        """
        Refresh buckets that haven't had any lookups in the last hour
        (per section 2.3 of the paper).
        """
        log.debug("Refreshing routing table")
        ds = []
        for node_id in self.protocol.getRefreshIDs():
            node = Node(node_id=node_id)
            nearest = self.protocol.router.findNeighbors(node, self.alpha)
            spider = NodeSpiderCrawl(self.protocol, node, nearest, self.ksize,
                                     self.alpha)
            ds.append(spider.find())

        # do our crawling
        await asyncio.gather(*ds)
示例#11
0
    def welcomeIfNewNode(self, node):
        """
        Given a new node, send it all the keys/values it should be storing,
        then add it to the routing table.

        @param node: A new node that just joined (or that we just found out
        about).

        Process:
        For each key in storage, get k closest nodes.  If newnode is closer
        than the furtherst in that list, and the node for this network
        is closer than the closest in that list, then store the key/value
        on the new node (per section 2.5 of the paper)
        """
        if not node:
            log.warning('This node is not welcomed.')
            return

        if not self.router.isNewNode(node):
            log.debug(
                "Skipping node {} that already exists in routing table".format(
                    node))
            return

        log.info("never seen %s before, adding to router", node)
        for key, value in self.storage.items():
            keynode = Node(digest(key))
            neighbors = self.router.findNeighbors(keynode)
            if len(neighbors) > 0:
                last = neighbors[-1].distanceTo(keynode)
                newNodeClose = node.distanceTo(keynode) < last
                first = neighbors[0].distanceTo(keynode)
                thisNodeClosest = self.sourceNode.distanceTo(keynode) < first
            if len(neighbors) == 0 or (newNodeClose and thisNodeClosest):
                asyncio.ensure_future(self.callStore(node, key, value))

        self.router.addContact(node)
        self.network.connect_to_neighbor(node)
示例#12
0
 def rpc_ping(self, sender, public_key, nodeid):
     source = Node(nodeid, sender[0], sender[1], public_key=public_key)
     self.welcomeIfNewNode(source)
     return self.sourceNode.id, self.sourceNode.public_key
示例#13
0
 def __init__(self, sourceID, ksize=20):
     self.router = RoutingTable(self, ksize, Node(sourceID))
     self.storage = {}
     self.sourceID = sourceID