コード例 #1
0
    def parse_command(self, name) -> Dict:
        """
        parse command from name part of packet
        :param name: name part of packet
        :type name: FormalName
        :return: Dict {(command, dataname, seq}
        """
        # assume following name
        # /prefix/opcode/dataname/params-sha256

        # convert FormalName to NonStrictName
        str_name = Name.to_str(name)
        # remove params-sha256 for Application Parameter
        oname = str_name.split("/params-sha256")[0]
        # split name part
        parts = oname.split("/")[1:]
        # check prefix
        command = "ERROR"
        cmd_list = list(PSKCmd.commands.values())
        if Name.is_prefix(self.net_name, oname):
            nname_cnt = len(self.net_name.split('/')[1:])
            if parts[nname_cnt] in cmd_list:
                command = parts[nname_cnt]
                d_begin = nname_cnt + 1
            else:
                command = parts[1]
                d_begin = 2
        elif Name.is_prefix(self.bro_name, oname):
            bname_cnt = len(self.bro_name.split('/')[1:])
            if parts[bname_cnt] in list(PSKCmd.commands.values()):
                command = parts[bname_cnt]
                d_begin = bname_cnt + 1
            else:
                command = parts[1]
                d_begin = 2
        seq = None
        wseq = 0
        # last index is sequence no.
        if command == PSKCmd.commands["CMD_PD"] or command == PSKCmd.commands[
                "CMD_SD"]:
            seq = parts[len(parts) - 1]
            wseq = 1
        # make dataname
        datas = parts[d_begin:(len(parts) - wseq)]
        dataname = "/" + "/".join(datas)
        # replace %xx escapes by their single-character equivalent
        udataname = urllib.parse.unquote(dataname)
        # if seq is Null, OK?
        return {"command": command, "dataname": udataname, "seq": seq}
コード例 #2
0
ファイル: name_test.py プロジェクト: zjkmxy/python-ndn
    def test_is_prefix():
        assert Name.is_prefix(Name.from_str('/'), Name.from_str('/'))
        assert Name.is_prefix(Name.from_str('/'), Name.from_str('/3=D'))
        assert Name.is_prefix(Name.from_str('/'), Name.from_str('/F'))
        assert Name.is_prefix(Name.from_str('/'), Name.from_str('/21426=AA'))

        assert Name.is_prefix(Name.from_str('/B'), Name.from_str('/B'))
        assert Name.is_prefix(Name.from_str('/B'), Name.from_str('/B/3=D'))
        assert Name.is_prefix(Name.from_str('/B'), Name.from_str('/B/F'))
        assert Name.is_prefix(Name.from_str('/B'),
                              Name.from_str('/B/21426=AA'))

        assert not Name.is_prefix(Name.from_str('/C'), Name.from_str('/'))
        assert not Name.is_prefix(Name.from_str('/C'), Name.from_str('/3=D'))
        assert not Name.is_prefix(Name.from_str('/C'), Name.from_str('/F'))
        assert not Name.is_prefix(Name.from_str('/C'),
                                  Name.from_str('/21426=AA'))
コード例 #3
0
    async def _process_insert(self, cmd_param: RepoCommandParameter):
        """
        Process segmented insertion command.
        Return to client with status code 100 immediately, and then start data fetching process.
        """
        try:
            name = cmd_param.name
            start_block_id = cmd_param.start_block_id
            end_block_id = cmd_param.end_block_id
            process_id = cmd_param.process_id
            if cmd_param.register_prefix:
                register_prefix = cmd_param.register_prefix.name
            else:
                register_prefix = None
            # support only 1 forwarding hint now
            if cmd_param.forwarding_hint and cmd_param.forwarding_hint.name:
                forwarding_hint = [(0x0, cmd_param.forwarding_hint.name)]
            else:
                forwarding_hint = None
            check_prefix = cmd_param.check_prefix.name
        except AttributeError:
            return

        logging.info(
            f'Write handle processing insert command: {Name.to_str(name)}, {start_block_id}, {end_block_id}'
        )

        # rejects any data that overlaps with repo's own namespace
        if Name.is_prefix(self.prefix, name) or Name.is_prefix(
                name, self.prefix):
            logging.warning('Inserted data name overlaps with repo prefix')
            return
        elif self.normalize_params_or_reject(cmd_param) == False:
            logging.warning('Insert command malformed')
            return

        # Reply to client with status code 100
        self.m_process_id_to_status[process_id] = RepoCommandResponse()
        self.m_process_id_to_status[process_id].process_id = process_id
        self.m_process_id_to_status[process_id].insert_num = 0
        self.m_process_id_to_check_prefix[process_id] = check_prefix

        # Remember the prefixes to register
        if register_prefix:
            is_existing = CommandHandle.add_registered_prefix_in_storage(
                self.storage, register_prefix)
            # If repo does not register root prefix, the client tells repo what to register
            if not self.register_root and not is_existing:
                self.m_read_handle.listen(register_prefix)

        # Remember the files inserted, this is useful for enumerating all inserted files
        CommandHandle.add_inserted_filename_in_storage(self.storage, name)

        # Start data fetching process
        self.m_process_id_to_status[process_id].status_code = 300
        insert_num = 0
        is_success = False
        if start_block_id != None:
            # Fetch data packets with block ids appended to the end
            insert_num = await self.fetch_segmented_data(
                name, start_block_id, end_block_id, forwarding_hint)
            if end_block_id is None or start_block_id + insert_num - 1 == end_block_id:
                is_success = True
        else:
            # Both start_block_id and end_block_id are None, fetch a single data packet
            insert_num = await self.fetch_single_data(name, forwarding_hint)
            if insert_num == 1:
                is_success = True

        if is_success:
            self.m_process_id_to_status[process_id].status_code = 200
            logging.info(
                'Insertion success, {} items inserted'.format(insert_num))
        else:
            self.m_process_id_to_status[process_id].status_code = 400
            logging.info(
                'Insertion failure, {} items inserted'.format(insert_num))
        self.m_process_id_to_status[process_id].insert_num = insert_num

        # Delete process state after some time
        await self._delete_process_state_after(process_id, 60)
コード例 #4
0
    async def _process_insert(self, cmd_param: RepoCommandParameter):
        """
        Process segmented insertion command.
        Return to client with status code 100 immediately, and then start data fetching process.
        """
        name = cmd_param.name
        start_block_id = cmd_param.start_block_id
        end_block_id = cmd_param.end_block_id
        process_id = cmd_param.process_id
        register_prefix = cmd_param.register_prefix

        logging.info(
            f'Write handle processing insert command: {Name.to_str(name)}, {start_block_id}, {end_block_id}'
        )

        # rejects any data that overlaps with repo's own namespace
        if Name.is_prefix(self.prefix, name) or Name.is_prefix(
                name, self.prefix):
            logging.warning('Inserted data name overlaps with repo prefix')
            return
        elif self.is_valid_param(cmd_param) == False:
            logging.warning(
                'Insert command malformed: only end_block_id is specified')
            return

        # Reply to client with status code 100
        self.m_processes[process_id] = RepoCommandResponse()
        self.m_processes[process_id].process_id = process_id
        self.m_processes[process_id].insert_num = 0

        # If repo does not register root prefix, the client tells repo what to register
        if not self.register_root:
            if not CommandHandle.add_prefixes_in_storage(
                    self.storage, register_prefix):
                self.m_read_handle.listen(register_prefix)

        # Start data fetching process
        self.m_processes[process_id].status_code = 300
        insert_num = 0
        is_success = False
        if start_block_id != None:
            # Fetch data packets with block ids appended to the end
            insert_num = await self.fetch_segmented_data(
                name, start_block_id, end_block_id)
            if end_block_id is None or start_block_id + insert_num - 1 == end_block_id:
                is_success = True
        else:
            # Both start_block_id and end_block_id are None, fetch a single data packet
            insert_num = await self.fetch_single_data(name)
            if insert_num == 1:
                is_success = True

        if is_success:
            self.m_processes[process_id].status_code = 200
            logging.info(
                'Insertion success, {} items inserted'.format(insert_num))
            #$ Trigger an Catalog Add Command

        else:
            self.m_processes[process_id].status_code = 400
            logging.info(
                'Insertion failure, {} items inserted'.format(insert_num))
        self.m_processes[process_id].insert_num = insert_num

        # Delete process state after some time
        await self.schedule_delete_process(process_id)
コード例 #5
0
ファイル: putfile.py プロジェクト: phylib/ndn-python-repo
    async def insert_file(self,
                          file_path: str,
                          name_at_repo: NonStrictName,
                          segment_size: int,
                          freshness_period: int,
                          cpu_count: int,
                          forwarding_hint: Optional[NonStrictName] = None,
                          register_prefix: Optional[NonStrictName] = None,
                          check_prefix: Optional[NonStrictName] = None) -> int:
        """
        Insert a file to remote repo.

        :param file_path: Local FS path to file to insert.
        :param name_at_repo: NonStrictName. Name used to store file at repo.
        :param segment_size: Max size of data packets.
        :param freshness_period: Freshness of data packets.
        :param cpu_count: Cores used for converting file to TLV format.
        :param forwarding_hint: NonStrictName. The forwarding hint the repo uses when fetching data.
        :param register_prefix: NonStrictName. If repo is configured with ``register_root=False``,\
            it registers ``register_prefix`` after receiving the insertion command.
        :param check_prefix: NonStrictName. The repo will publish process check messages under\
            ``<check_prefix>/check``. It is necessary to specify this value in the param, instead\
            of using a predefined prefix, to make sure the subscriber can register this prefix\
            under the NDN prefix registration security model. If not specified, default value is\
            the client prefix.
        :return: Number of packets inserted.
        """
        self._prepare_data(file_path, name_at_repo, segment_size,
                           freshness_period, cpu_count)
        num_packets = len(self.encoded_packets[Name.to_str(name_at_repo)])
        if num_packets == 0:
            return 0

        # If the uploaded file has the client's name as prefix, set an interest filter
        # for handling corresponding Interests from the repo
        if Name.is_prefix(self.prefix, name_at_repo):
            self.app.set_interest_filter(name_at_repo, self._on_interest)
        else:
            # Otherwise, register the file name as prefix for responding interests from the repo
            logging.info(
                f'Register prefix for file upload: {Name.to_str(name_at_repo)}'
            )
            await self.app.register(name_at_repo, self._on_interest)

        # construct insert cmd msg
        cmd_param = RepoCommandParameter()
        cmd_param.name = name_at_repo
        cmd_param.forwarding_hint = ForwardingHint()
        cmd_param.forwarding_hint.name = forwarding_hint
        cmd_param.start_block_id = 0
        cmd_param.end_block_id = num_packets - 1
        process_id = os.urandom(4)
        cmd_param.process_id = process_id
        cmd_param.register_prefix = RegisterPrefix()
        cmd_param.register_prefix.name = register_prefix
        if check_prefix == None:
            check_prefix = self.prefix
        cmd_param.check_prefix = CheckPrefix()
        cmd_param.check_prefix.name = check_prefix
        cmd_param_bytes = cmd_param.encode()

        # publish msg to repo's insert topic
        await self.pb.wait_for_ready()
        is_success = await self.pb.publish(self.repo_name + ['insert'],
                                           cmd_param_bytes)
        if is_success:
            logging.info(
                'Published an insert msg and was acknowledged by a subscriber')
        else:
            logging.info(
                'Published an insert msg but was not acknowledged by a subscriber'
            )

        # wait until finish so that repo can finish fetching the data
        insert_num = 0
        if is_success:
            insert_num = await self._wait_for_finish(check_prefix, process_id)
        return insert_num