示例#1
0
    def test_03_send_ping(self):
        print("\n-----", sys._getframe().f_code.co_name, "-----")
        for i in range(1, core_nodes):
            print("node=%d: ping_to:%s" % (i, binascii.b2a_hex(nodes[0])))
            query_entry = query_management.QueryEntry(
                expire_after=2,
                callback_expire=get_test_func_failure,
                data={},
                retry_count=1)
            query_entry.update(2, callback=get_test_func_success)
            ret = cores[i].networking.domains[domain_id].send_ping(
                nodes[0], query_entry.nonce)
            assert ret
        print("wait queue: 9")
        total = wait_results(9)
        assert total == 9
        cores[0].networking.domains[domain_id].print_peerlist()

        query_entry = query_management.QueryEntry(
            expire_after=2,
            callback_expire=get_test_func_failure,
            data={},
            retry_count=1)
        query_entry.update(2, callback=get_test_func_success)
        ret = cores[2].networking.domains[domain_id].send_ping(
            nodes[3], query_entry.nonce)
        assert not ret
        print("wait queue: 1 (** should fail to send)")
        total = wait_results(1)
        assert total == 0
示例#2
0
 def alive_check(self):
     query_entry = query_management.QueryEntry(expire_after=15,
                                               callback_expire=self.broadcast_peerlist,
                                               data={KeyType.peer_info: [],
                                                     'number_of_ping': len(self.id_ip_mapping)},
                                               retry_count=0)
     for nd in self.id_ip_mapping.keys():
         query_entry2 = query_management.QueryEntry(expire_after=14,
                                                    callback_expire=None,
                                                    callback=self.add_advertise_list,
                                                    callback_error=self.ping_with_retry,
                                                    interval=3,
                                                    data={KeyType.node_id: nd,
                                                          'parent_nonce': query_entry.nonce})
         self.ping_with_retry(query_entry2)
示例#3
0
    def send_domain_ping(self, domain_id, ipv4, ipv6, port, is_static=False):
        """
        (internal use) Send raw message to the specified node

        :param domain_id:
        :param ipv4:
        :param ipv6:
        :param port:
        :param is_static:
        :return:
        """
        if domain_id not in self.domains:
            return False
        if ipv4 is None and ipv6 is None:
            return False
        node_id = self.domains[domain_id]['neighbor'].my_node_id
        nodeinfo = NodeInfo(ipv4=ipv4,
                            ipv6=ipv6,
                            port=port,
                            is_static=is_static)
        query_entry = query_management.QueryEntry(
            expire_after=10,
            callback_error=self.domain_ping,
            callback_expire=self.invalidate_neighbor,
            data={
                KeyType.domain_id: domain_id,
                KeyType.node_id: node_id,
                KeyType.node_info: nodeinfo
            },
            retry_count=3)
        self.domain_ping(query_entry)
        return True
示例#4
0
 def _update_cross_ref_timer_entry(self):
     """Update cross_ref timer"""
     rand_interval = random.randint(int(Domain0Manager.DOMAIN_ACCEPTANCE_RECOVER_INTERVAL * 5 / 6),
                                    int(Domain0Manager.DOMAIN_ACCEPTANCE_RECOVER_INTERVAL * 7 / 6))
     self.logger.debug("update_cross_ref_timer_entry: %d" % rand_interval)
     self.cross_ref_timer_entry = query_management.QueryEntry(
             expire_after=rand_interval, callback_expire=self._purge_left_cross_ref, retry_count=0)
示例#5
0
 def _update_advertise_timer_entry(self):
     """Update advertisement timer"""
     rand_interval = random.randint(int(Domain0Manager.DOMAIN_INFO_ADVERTISE_INTERVAL * 5 / 6),
                                    int(Domain0Manager.DOMAIN_INFO_ADVERTISE_INTERVAL * 7 / 6))
     self.logger.debug("_update_advertise_timer_entry: %d" % rand_interval)
     self.advertise_timer_entry = query_management.QueryEntry(
             expire_after=rand_interval, callback_expire=self._advertise_domain_info, retry_count=0)
示例#6
0
 def test_03_callback_expire(self):
     print("\n-----", sys._getframe().f_code.co_name, "-----")
     entry = query_management.QueryEntry(expire_after=5,
                                         callback_expire=callback_expire,
                                         data=[4, 4, 4])
     total = wait_results(1)
     assert total == -1
示例#7
0
    def _add_user_for_forwarding(self, user_id, node_id, permanent=False):
        """Register user to forwarding list

        Args:
            user_id (bytes): target user_id
            node_id (bytes): node_id which the client with the user_id connects to
            parmanent (bool): If True, the entry won't expire
        """
        self.forwarding_entries.setdefault(user_id, dict())
        if not permanent:
            if 'refresh' not in self.forwarding_entries[user_id]:
                query_entry = query_management.QueryEntry(
                    expire_after=UserMessageRouting.
                    REFRESH_FORWARDING_LIST_INTERVAL,
                    callback_expire=self._remove_user_from_forwarding,
                    data={
                        KeyType.user_id: user_id,
                    },
                    retry_count=0)
                self.forwarding_entries[user_id]['refresh'] = query_entry
            else:
                self.forwarding_entries[user_id]['refresh'].update(
                    fire_after=UserMessageRouting.
                    REFRESH_FORWARDING_LIST_INTERVAL)
        self.forwarding_entries[user_id].setdefault('nodes', set())
        self.forwarding_entries[user_id]['nodes'].add(node_id)
        self.stats.update_stats("user_message",
                                "registered_users_in_forwarding_list",
                                len(self.forwarding_entries))
示例#8
0
    def _resolve_accommodating_core_node(self,
                                         dst_user_id,
                                         src_user_id,
                                         orig_msg=None):
        """Resolve which node the user connects to

        Find the node that accommodates the user_id first, and then, send the message to the node.

        Args:
            dst_user_id (bytes): destination user_id
            src_user_id (bytes): source user_id
            orig_msg (dict): message to send
        """
        if orig_msg is not None:
            query_entry = query_management.QueryEntry(
                expire_after=UserMessageRouting.RESOLVE_TIMEOUT,
                callback_expire=self._resolve_failure,
                callback=self._resolve_success,
                data={
                    KeyType.message: orig_msg,
                },
                retry_count=0)
            self.on_going_timers.add(query_entry.nonce)
        msg = {
            KeyType.infra_msg_type: InfraMessageCategory.CATEGORY_USER,
            KeyType.domain_id: self.domain_id,
            KeyType.infra_command: UserMessageRouting.RESOLVE_USER_LOCATION,
            KeyType.destination_user_id: dst_user_id,
        }
        if orig_msg is not None:
            msg[KeyType.nonce] = query_entry.nonce
        if src_user_id is not None:
            msg[KeyType.source_user_id] = src_user_id
        self.networking.broadcast_message_in_network(domain_id=self.domain_id,
                                                     msg=msg)
示例#9
0
    def send_raw_message(self, domain_id, ipv4, ipv6, port):
        """
        (internal use) Send raw message to the specified node

        :param domain_id:
        :param ipv4:
        :param ipv6:
        :param port:
        :return:
        """
        if domain_id not in self.domains:
            return False
        node_id = self.domains[domain_id].node_id
        nodeinfo = NodeInfo(ipv4=ipv4, ipv6=ipv6, port=port)
        query_entry = query_management.QueryEntry(expire_after=10,
                                                  callback_error=self.raw_ping,
                                                  data={
                                                      KeyType.domain_id:
                                                      domain_id,
                                                      KeyType.node_id: node_id,
                                                      KeyType.peer_info:
                                                      nodeinfo
                                                  },
                                                  retry_count=3)
        self.raw_ping(query_entry)
        return True
示例#10
0
    def get_domain_keypair(self, domain_id):
        """Get domain_keys (private key and public key)

        Args:
            domain_id (bytes): target domain_id
        """
        keyconfig = self.config.get_config().get('domain_key', None)
        if keyconfig is None:
            self.domains[domain_id]['keypair'] = None
            return
        if 'use' not in keyconfig or not keyconfig['use']:
            return
        if 'directory' not in keyconfig or not os.path.exists(keyconfig['directory']):
            self.domains[domain_id]['keypair'] = None
            return
        domain_id_str = domain_id.hex()
        keypair = bbclib.KeyPair()
        try:
            with open(os.path.join(keyconfig['directory'], domain_id_str+".pem"), "r") as f:
                keypair.mk_keyobj_from_private_key_pem(f.read())
        except:
            self.domains[domain_id]['keypair'] = None
            return
        self.domains[domain_id].setdefault('keypair', dict())
        self.domains[domain_id]['keypair'].setdefault('keys', list())
        self.domains[domain_id]['keypair']['keys'].insert(0, keypair)
        timer = self.domains[domain_id]['keypair'].setdefault('timer', None)
        if timer is None or not timer.active:
            self.domains[domain_id]['keypair']['timer'] = query_management.QueryEntry(
                expire_after=keyconfig['obsolete_timeout'],
                data={KeyType.domain_id: domain_id}, callback_expire=self._delete_obsoleted_domain_keys)
        else:
            timer.update_expiration_time(keyconfig['obsolete_timeout'])
        self.domains[domain_id]['keypair']['keys'].insert(0, keypair)
示例#11
0
    def send_domain_ping(self, domain_id, ipv4, ipv6, port, is_static=False):
        """Send domain ping to the specified node

        Args:
            domain_id (bytes): target domain_id
            ipv4 (str): IPv4 address of the node
            ipv6 (str): IPv6 address of the node
            port (int): Port number
            is_static (bool): If true, the entry is treated as static one and will be saved in config.json
        Returns:
            bool: True if successful
        """
        if domain_id not in self.domains:
            return False
        if ipv4 is None and ipv6 is None:
            return False
        node_id = self.domains[domain_id]['neighbor'].my_node_id
        nodeinfo = NodeInfo(ipv4=ipv4,
                            ipv6=ipv6,
                            port=port,
                            is_static=is_static)
        query_entry = query_management.QueryEntry(
            expire_after=10,
            callback_error=self._domain_ping,
            callback_expire=self._invalidate_neighbor,
            data={
                KeyType.domain_id: domain_id,
                KeyType.node_id: node_id,
                KeyType.node_info: nodeinfo
            },
            retry_count=3)
        self._domain_ping(query_entry)
        return True
示例#12
0
    def test_06_multiple_entries_normal_error_expire(self):
        print("\n-----", sys._getframe().f_code.co_name, "-----")
        query_entries = []
        for i in range(10):
            entry = query_management.QueryEntry(
                expire_after=5,
                callback_expire=callback_expire,
                callback=callback_normal,
                callback_error=callback_error,
                data=[i, 0, 6])
            entry.update(2)
            query_entries.append(entry.nonce)
        time.sleep(1)

        # -- normal
        for i in range(10):
            entry = ticker.get_entry(query_entries[i])
            entry.callback()
        total = wait_results(10)
        assert total == 10

        # -- error
        for i in range(10):
            entry = ticker.get_entry(query_entries[i])
            entry.update(1)
        total = wait_results(10)
        assert total == 0

        # -- finally
        time.sleep(5)
        total = wait_results(10)
        assert total == -10
示例#13
0
    def test_04_alive_check(self):
        print("\n-----", sys._getframe().f_code.co_name, "-----")
        for i in range(core_nodes):
            cores[i].networking.domains[domain_id].print_peerlist()

        cores[0].networking.domains[domain_id].alive_check()
        print("** wait 5 sec to finish alive_check")
        time.sleep(5)
        assert len(
            cores[1].networking.domains[domain_id].id_ip_mapping) == 10 - 1

        query_entry = query_management.QueryEntry(
            expire_after=2,
            callback_expire=get_test_func_failure,
            data={},
            retry_count=1)
        query_entry.update(2, callback=get_test_func_success)
        ret = cores[2].networking.domains[domain_id].send_ping(
            nodes[3], query_entry.nonce)
        assert ret
        print("wait queue: 1")
        total = wait_results(1)
        assert total == 1

        for i in range(core_nodes):
            cores[i].networking.domains[domain_id].print_peerlist()
示例#14
0
 def purge(self, query_entry):
     for node_id in list(self.nodeinfo_list.keys()):
         if not self.nodeinfo_list[node_id].is_alive:
             self.nodeinfo_list.pop(node_id, None)
     self.purge_timer = query_management.QueryEntry(
         expire_after=NeighborInfo.PURGE_INTERVAL_SEC,
         callback_expire=self.purge,
         retry_count=3)
示例#15
0
 def purge(self, query_entry):
     """Purge obsoleted entry in nodeinfo_list"""
     for node_id in list(self.nodeinfo_list.keys()):
         if not self.nodeinfo_list[node_id].is_alive or self.nodeinfo_list[node_id].updated_at + \
                 NeighborInfo.NODEINFO_LIFETIME < time.time():
             self.nodeinfo_list.pop(node_id, None)
     self.purge_timer = query_management.QueryEntry(expire_after=NeighborInfo.PURGE_INTERVAL_SEC,
                                                    callback_expire=self.purge, retry_count=3)
示例#16
0
 def _set_delete_timer(self, key_name, timeout):
     """Set timer for key revocation"""
     if key_name is not None:
         #print("(%d) _set_delete_timer:" % int(time.time()), key_name.hex()[:10], timeout)
         query_management.QueryEntry(expire_after=timeout,
                                     callback_expire=remove_old_key,
                                     data={KeyType.hint: key_name},
                                     retry_count=0)
示例#17
0
 def add_node(self, node_id):
     if node_id not in self.asset_groups:
         self.asset_groups[node_id] = query_management.QueryEntry(expire_after=ASSET_GROUP_INFO_LIFETIME,
                                                                  callback_expire=self.remove_entry,
                                                                  data={KeyType.node_id: node_id},
                                                                  retry_count=0)
     else:
         self.asset_groups[node_id].update_expiration_time(ASSET_GROUP_INFO_LIFETIME)
示例#18
0
 def set_invoke_timer(self, timeout, retry_entry=False):
     if self.timer_entry is not None and self.timer_entry.active:
         self.timer_entry.deactivate()
     #print("(%d) set_invoke_timer:" % int(time.time()), timeout)
     self.timer_entry = query_management.QueryEntry(expire_after=timeout,
                                                    callback_expire=self.perform_key_exchange,
                                                    retry_count=0)
     if retry_entry:
         self.timer_entry.data[KeyType.retry_timer] = True
示例#19
0
 def __init__(self, network=None, domain_id=None, node_id=None, my_info=None):
     self.networking = network
     self.domain_id = domain_id
     self.my_node_id = node_id
     self.my_info = my_info
     self.admin_sequence_number = 0
     self.nodeinfo_list = dict()
     self.purge_timer = query_management.QueryEntry(expire_after=NeighborInfo.PURGE_INTERVAL_SEC,
                                                    callback_expire=self.purge, retry_count=3)
示例#20
0
 def test_02_normal_callback(self):
     print("\n-----", sys._getframe().f_code.co_name, "-----")
     entry = query_management.QueryEntry(expire_after=2,
                                         callback_expire=callback_expire,
                                         callback=callback_normal,
                                         callback_error=callback_error,
                                         data=[2, 2, 2])
     entry.update(fire_after=1.5)
     time.sleep(1)
     entry.callback()  # entry is deactivated in the callback
     total = wait_results(1)
     assert total == 1
示例#21
0
 def test_04_expire_callback_reschedule(self):
     print("\n-----", sys._getframe().f_code.co_name, "-----")
     entry = query_management.QueryEntry(expire_after=2,
                                         callback_expire=callback_expire,
                                         callback=callback_normal,
                                         callback_error=callback_error,
                                         data=[3, 3, 3])
     entry.update(expire_after=1.5)
     time.sleep(1.6)
     entry.deactivate()
     total = wait_results(1)
     assert total == -1
示例#22
0
 def test_02_deactivate(self):
     print("\n-----", sys._getframe().f_code.co_name, "-----")
     entry = query_management.QueryEntry(expire_after=3,
                                         callback_expire=callback_expire,
                                         callback=callback_normal,
                                         callback_error=callback_error,
                                         interval=2,
                                         data=[2.5, 2.5, 2.5],
                                         retry_count=1)
     print("**sleep 2.5 sec")
     time.sleep(2.5)
     entry.deactivate()
示例#23
0
 def put_resource(self, asset_group_id, resource_id, resource_type, resource):
     for nd in self.get_neighbor_nodes():
         entry = query_management.QueryEntry(expire_after=30,
                                             callback_expire=None,
                                             callback_error=self.resend_resource,
                                             data={'target_id': nd,
                                                   KeyType.asset_group_id: asset_group_id,
                                                   KeyType.resource_id: resource_id,
                                                   KeyType.resource: resource,
                                                   KeyType.resource_type: resource_type},
                                             retry_count=2)
         entry.update(INTERVAL_RETRY)
         self.send_store(nd, entry.nonce, asset_group_id, resource_id, resource, resource_type)
示例#24
0
    def route_message(self,
                      domain_id=ZEROS,
                      asset_group_id=None,
                      dst_user_id=None,
                      src_user_id=None,
                      msg_to_send=None,
                      payload_type=PayloadType.Type_msgpack):
        """
        Find the destination host and send it

        :param domain_id:
        :param asset_group_id:
        :param src_user_id:   source user
        :param dst_user_id:   destination user
        :param msg_to_send:   content to send
        :param payload_type:  PayloadType value
        :return:
        """
        if domain_id not in self.domains:
            return False

        self.logger.debug("route_message to dst_user_id:%s" %
                          (binascii.b2a_hex(dst_user_id[:2])))
        if self.domains[domain_id].is_registered_user(asset_group_id,
                                                      dst_user_id):
            self.logger.debug(" -> directly to the app")
            self.core.send_message(msg_to_send)
            return True

        query_entry = query_management.QueryEntry(
            expire_after=DURATION_GIVEUP_PUT,
            callback_expire=self.callback_route_failure,
            callback=self.forward_message,
            callback_error=self.domains[domain_id].send_p2p_message,
            interval=INTERVAL_RETRY,
            data={
                KeyType.domain_id: domain_id,
                KeyType.asset_group_id: asset_group_id,
                KeyType.source_node_id: src_user_id,
                KeyType.resource_id: dst_user_id,
                'payload_type': payload_type,
                'msg_to_send': msg_to_send
            },
            retry_count=ROUTE_RETRY_COUNT)
        self.domains[domain_id].send_p2p_message(query_entry)
        return True
示例#25
0
 def test_12_get(self):
     print("-----", sys._getframe().f_code.co_name, "-----")
     query_entry = query_management.QueryEntry(
         expire_after=10,
         callback_expire=get_test_func_failure,
         data={
             KeyType.domain_id: domain_id,
             KeyType.asset_group_id: asset_group_id,
             KeyType.resource_id: sample_resource_id,
             KeyType.resource_type: ResourceType.Transaction_data
         },
         retry_count=3)
     query_entry.update(2, callback=get_test_func_success)
     networkings[1].get(query_entry)
     print("wait queue: 1")
     total = wait_results(1)
     assert total == 1
示例#26
0
    def test_05_multiple_entries_normal(self):
        print("\n-----", sys._getframe().f_code.co_name, "-----")
        query_entries = []
        for i in range(10):
            entry = query_management.QueryEntry(
                expire_after=4,
                callback_expire=callback_expire,
                callback=callback_normal,
                callback_error=callback_error,
                data=[i, 0, 5])
            entry.update(fire_after=2)
            query_entries.append(entry.nonce)

        time.sleep(1)
        for i in range(10):
            entry = ticker.get_entry(query_entries[i])
            entry.callback()
            ticker.del_entry(query_entries[i])
        total = wait_results(10)
        assert total == 10
示例#27
0
    def ping_with_retry(self, query_entry=None, node_id=None, retry_count=3):
        """
        Retry ping if response is not received within a given time

        :param query_entry:
        :param node_id:     target node_id (need for first trial)
        :param retry_count:
        :return:
        """
        if node_id is not None:
            query_entry = query_management.QueryEntry(
                expire_after=ALIVE_CHECK_PING_WAIT,
                callback_error=self.ping_with_retry,
                interval=1,
                data={KeyType.node_id: node_id},
                retry_count=retry_count)
        else:
            node_id = query_entry.data[KeyType.node_id]
        query_entry.update()
        self.send_ping(node_id, nonce=query_entry.nonce)
示例#28
0
 def update_refresh_timer_entry(self,
                                new_entry=True,
                                force_refresh_time=None):
     if force_refresh_time is None:
         rand_interval = random.randint(
             int(TopologyManagerBase.NEIGHBOR_LIST_REFRESH_INTERVAL * 2 /
                 3),
             int(TopologyManagerBase.NEIGHBOR_LIST_REFRESH_INTERVAL * 4 /
                 3))
     else:
         rand_interval = force_refresh_time
     self.logger.debug("update_refresh_timer_entry: %d" % rand_interval)
     if new_entry:
         self.neighbor_refresh_timer_entry = query_management.QueryEntry(
             expire_after=rand_interval,
             data={"is_refresh": True},
             callback_expire=self.advertise_neighbor_info,
             retry_count=0)
     else:
         self.neighbor_refresh_timer_entry.update_expiration_time(
             rand_interval)
示例#29
0
    def add_peer_node_ip46(self, node_id, ipv4, ipv6, port):
        """
        Add as a peer node (with ipv4 and ipv6 address)

        :param node_id:
        :param ipv4:
        :param ipv6:
        :param port:
        :return:
        """
        self.logger.debug(
            "[%s] add_peer_node_ip46: nodeid=%s, port=%d" %
            (self.shortname, binascii.b2a_hex(node_id[:2]), port))
        self.id_ip_mapping[node_id] = NodeInfo(node_id=node_id,
                                               ipv4=ipv4,
                                               ipv6=ipv6,
                                               port=port)
        query_entry = query_management.QueryEntry(
            expire_after=ALIVE_CHECK_PING_WAIT,
            callback_expire=self.ping_response_check,
            data={KeyType.node_id: node_id},
            retry_count=0)
        self.ping_with_retry(node_id=node_id, retry_count=3)
示例#30
0
    def notify_neighbor_update(self, node_id, is_new=True):
        """Update expiration timer for the notified node_id

        Args:
            node_id (bytes): target node_id
            is_new (bool): If True, this node is a new comer node
        """
        if node_id is not None:
            self.logger.debug(
                "[%s] notify_neighbor_update: node_id=%s, is_new=%s" %
                (self.my_node_id.hex()[:4], node_id.hex()[:4], is_new))
        else:
            self.logger.debug("[%s] notify_neighbor_update" %
                              self.my_node_id.hex()[:4])

        rand_time = random.uniform(
            0.5, 1) * 5 / (len(self.neighbors.nodeinfo_list) + 1)
        if self.advertise_wait_entry is None:
            self.advertise_wait_entry = query_management.QueryEntry(
                expire_after=rand_time,
                callback_expire=self._advertise_neighbor_info,
                retry_count=0)
        else:
            self.advertise_wait_entry.update_expiration_time(rand_time)