예제 #1
0
 def make_subdata_cmd(self,
                      prefix,
                      dataname,
                      seq,
                      lifetime=None,
                      subinfo: SubInfo = None) -> (str, Any):
     """
     make subdata command
     :param prefix: datarn_prefix
     :type prefix: str
     :param dataname: dataname
     :type dataname: str
     :param seq: sequence no.
     :type seq: int
     :param subinfo: subinfo
     :type subinfo: SubInfo
     :return: command, interest_param, app_param
     """
     # make a subdatareq command name with args
     #command = Name.to_str(prefix + "/" + CMD_SUBDATAREQ + dataname + f'/{seq:d}')
     command = prefix + "/" + PSKCmd.commands[
         "CMD_SD"] + dataname + "/" + str(seq)
     # set interest parameter
     i_param = InterestParam()
     i_param.must_be_fresh = True
     i_param.nonce = gen_nonce()
     i_param.lifetime = (lifetime if lifetime else INT_LT_10)
     # make a app_params for subscription
     param = PSKParameters(subinfo=subinfo)
     str_app_param = json.dumps(param, default=serialize)
     return command, i_param, bytes(str_app_param, 'utf-8')
예제 #2
0
    def test_app_param():
        name = '/local/ndn/prefix'
        app_param = b'\x01\x02\x03\x04'
        interest, final_name = make_interest(name,
                                             InterestParam(),
                                             app_param,
                                             need_final_name=True)
        assert (
            interest ==
            b'\x05\x42\x07\x36\x08\x05local\x08\x03ndn\x08\x06prefix'
            b'\x02 \x47\x75\x6f\x21\xfe\x0e\xe2\x65\x14\x9a\xa2\xbe\x3c\x63\xc5\x38'
            b'\xa7\x23\x78\xe9\xb0\xa5\x8b\x39\xc5\x91\x63\x67\xd3\x5b\xda\x10'
            b'\x0c\x02\x0f\xa0\x24\x04\x01\x02\x03\x04')
        assert (final_name == Name.decode(
            b'\x07\x36\x08\x05local\x08\x03ndn\x08\x06prefix'
            b'\x02 \x47\x75\x6f\x21\xfe\x0e\xe2\x65\x14\x9a\xa2\xbe\x3c\x63\xc5\x38'
            b'\xa7\x23\x78\xe9\xb0\xa5\x8b\x39\xc5\x91\x63\x67\xd3\x5b\xda\x10'
        )[0])

        name = '/test/params-sha256=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/ndn'
        interest = make_interest(name, InterestParam(), app_param)
        assert (
            interest == b'\x05\x39\x07\x2d\x08\x04test'
            b'\x02 \x47\x75\x6f\x21\xfe\x0e\xe2\x65\x14\x9a\xa2\xbe\x3c\x63\xc5\x38'
            b'\xa7\x23\x78\xe9\xb0\xa5\x8b\x39\xc5\x91\x63\x67\xd3\x5b\xda\x10'
            b'\x08\x03ndn'
            b'\x0c\x02\x0f\xa0\x24\x04\x01\x02\x03\x04')
예제 #3
0
 def make_irdel_cmd(self,
                    prefix,
                    dataname,
                    rawpacket: BinaryStr = None) -> (str, Any):
     """
     make irdel command
     :param prefix: ir_prefix
     :type prefix: str
     :param dataname: dataname
     :type dataname: str
     :param rawpacket: raw interest packet
     :type bytes: 
     :return: command, interest_param, app_param
     """
     # make a irmod command name with args
     command = prefix + "/" + PSKCmd.commands["CMD_MD"] + dataname
     # set interest parameter
     i_param = InterestParam()
     i_param.must_be_fresh = True
     i_param.nonce = gen_nonce()
     i_param.lifetime = INT_LT_4
     # make app_param for Infomation Registry (raw interest packet)
     str_rawpacket = rawpacket.decode('utf-8')
     param = PSKParameters(rawpacket=str_rawpacket)
     str_app_param = json.dumps(param, default=serialize)
     return command, i_param, bytes(str_app_param, 'utf-8')
예제 #4
0
 def make_pubdata_cmd(self,
                      prefix,
                      dataname,
                      seq,
                      pubdatainfo: PubDataInfo = None) -> (str, Any):
     """
     make pubdata command
     :param prefix: network_prefix
     :type prefix: str
     :param dataname: dataname for publishing data
     :type dataname: str
     :param seq: sequence no.
     :type seq: int
     :param pubed_data: pubed data
     :type pubed_data: any
     :return: command, interest_param, app_param
     """
     # make a pubdata command name with args
     command = prefix + "/" + PSKCmd.commands[
         "CMD_PD"] + dataname + '/' + str(seq)
     # set interest parameter
     i_param = InterestParam()
     i_param.must_be_fresh = True
     i_param.nonce = gen_nonce()
     i_param.lifetime = INT_LT_4
     param = PSKParameters(pubdatainfo=pubdatainfo)
     str_app_param = json.dumps(param, default=serialize)
     return command, i_param, bytes(str_app_param, 'utf-8')
예제 #5
0
 def make_subtopic_cmd(self,
                       prefix,
                       dataname,
                       subinfo: SubInfo = None) -> (str, Any):
     """
     make subtopic command
     :param prefix: network_prefix or topicrn_prefix
     :type prefix: str
     :param dataname: topic name
     :type dataname: str
     :param subinfo: subscription information
     :type subinfo: SubInfo
     :return: command, interest_param, app_param
     """
     # make a subtopic command name with args
     command = prefix + "/" + PSKCmd.commands["CMD_ST"] + dataname
     # set interest parameter
     i_param = InterestParam()
     i_param.must_be_fresh = True
     i_param.nonce = gen_nonce()
     i_param.lifetime = INT_LT_10
     # make a app_params for subscription
     param = PSKParameters(subinfo=subinfo)
     str_app_param = json.dumps(param, default=serialize)
     return command, i_param, bytes(str_app_param, 'utf-8')
예제 #6
0
    def test_signed_interest():
        name = '/local/ndn/prefix'
        app_param = b'\x01\x02\x03\x04'
        int_param = InterestParam()
        int_param.nonce = 0x6c211166
        interest = make_interest(name, int_param, app_param, signer=DigestSha256Signer())
        assert (interest ==
                b'\x05\x6f\x07\x36\x08\x05local\x08\x03ndn\x08\x06prefix'
                b'\x02 \x8e\x6e\x36\xd7\xea\xbc\xde\x43\x75\x61\x40\xc9\x0b\xda\x09\xd5'
                b'\x00\xd2\xa5\x77\xf2\xf5\x33\xb5\x69\xf0\x44\x1d\xf0\xa7\xf9\xe2'
                b'\x0a\x04\x6c\x21\x11\x66\x0c\x02\x0f\xa0'
                b'\x24\x04\x01\x02\x03\x04'
                b'\x2c\x03\x1b\x01\x00'
                b'\x2e \xea\xa8\xf0\x99\x08\x63\x78\x95\x1d\xe0\x5f\xf1\xde\xbb\xc1\x18'
                b'\xb5\x21\x8b\x2f\xca\xa0\xb5\x1d\x18\xfa\xbc\x29\xf5\x4d\x58\xff')

        interest = make_interest(name, int_param, signer=DigestSha256Signer())
        assert (interest ==
                b'\x05\x6b\x07\x36\x08\x05local\x08\x03ndn\x08\x06prefix'
                b'\x02 \x40\x77\xa5\x70\x49\xd8\x38\x48\xb5\x25\xa4\x23\xab\x97\x8e\x64'
                b'\x80\xf9\x6d\x5c\xa3\x8a\x80\xa5\xe2\xd6\xe2\x50\xa6\x17\xbe\x4f'
                b'\x0a\x04\x6c\x21\x11\x66\x0c\x02\x0f\xa0'
                b'\x24\x00'
                b'\x2c\x03\x1b\x01\x00'
                b'\x2e \x09\x4e\x00\x9d\x74\x59\x82\x5c\xa0\x2d\xaa\xb7\xad\x60\x48\x30'
                b'\x39\x19\xd8\x99\x80\x25\xbe\xff\xa6\xf9\x96\x79\xd6\x5e\x9f\x62')
예제 #7
0
 def make_pubadv_cmd(self,
                     prefix: str,
                     dataname: str,
                     pubadvinfo: PubAdvInfo = None,
                     irinfo: IRInfo = None,
                     rninfo: RNInfo = None) -> (str, Any):
     """
     make pubadv command
     :param prefix: network_prefix or broker_prefix
     :type prefix: str
     :param dataname: dataname for publishing data
     :type dataname: str
     :param pubinfo: pubadvinfo
     :type pubinfo: PubAdvInfo
     :param irinfo: irinfo
     :type irinfo: IRInfo
     :param rninfo: rninfo
     :type rninfo: RNInfo
     :return: command, interest_param, app_param
     """
     # make a pubadv command name with args
     #command = Name.to_str(prefix + "/" + CMD_PUBADV + dataname)
     command = prefix + "/" + PSKCmd.commands["CMD_PA"] + dataname
     # set interest parameter
     i_param = InterestParam()
     i_param.must_be_fresh = True
     i_param.nonce = gen_nonce()
     i_param.lifetime = INT_LT_10
     param = PSKParameters(pubadvinfo=pubadvinfo,
                           irinfo=irinfo,
                           rninfo=rninfo)
     str_app_param = json.dumps(param, default=serialize)
     return command, i_param, bytes(str_app_param, 'utf-8')
예제 #8
0
 def make_generic_cmd(self,
                      command: str,
                      prefix: str,
                      dataname: str = "/_",
                      pubadvinfo: PubAdvInfo = None,
                      irinfo: IRInfo = None,
                      rninfo: RNInfo = None,
                      **kwargs) -> (str, Any):
     """
     make generic command
     :param prefix: network_prefix or broker_prefix
     :type prefix: str
     :param dataname: dataname for publishing data
     :type dataname: str
     :param pubinfo: pubadvinfo
     :type pubinfo: PubAdvInfo
     :param irinfo: irinfo
     :type irinfo: IRInfo
     :param rninfo: rninfo
     :type rninfo: RNInfo
     :return: command, interest_param, app_param
     """
     command = prefix + "/" + command + dataname
     # set interest parameter
     i_param = InterestParam()
     i_param.must_be_fresh = True
     i_param.nonce = gen_nonce()
     i_param.lifetime = INT_LT_10
     param = PSKParameters(pubadvinfo=pubadvinfo,
                           irinfo=irinfo,
                           rninfo=rninfo,
                           **kwargs)
     str_app_param = json.dumps(param, default=serialize)
     return command, i_param, bytes(str_app_param, 'utf-8')
예제 #9
0
    async def _process_notify_interest(self, int_name, int_param, app_param):
        """
        Async helper for ``_on_notify_interest()``.
        """
        logging.debug(f'received notify interest: {Name.to_str(int_name)}')
        topic = int_name[:-2]  # remove digest and `notify`

        # parse notify interest
        app_param = NotifyAppParam.parse(app_param)
        publisher_prefix = app_param.publisher_prefix
        notify_nonce = app_param.notify_nonce
        publisher_fwd_hint = app_param.publisher_fwd_hint
        int_param = InterestParam()
        if publisher_fwd_hint:
            # support only 1 forwarding hint now
            int_param.forwarding_hint = [(0x0, publisher_fwd_hint.name)]

        # send msg interest, retransmit 3 times
        msg_int_name = publisher_prefix + ['msg'] + topic + [
            Component.from_bytes(notify_nonce)
        ]
        n_retries = 3

        # de-duplicate notify interests of the same nonce
        if notify_nonce in self.nonce_processed:
            logging.info(
                f'Received duplicate notify interest for nonce {notify_nonce}')
            return
        self.nonce_processed.add(notify_nonce)
        aio.ensure_future(self._erase_subsciber_state_after(notify_nonce, 60))

        while n_retries > 0:
            try:
                logging.debug(
                    f'sending msg interest: {Name.to_str(msg_int_name)}')
                data_name, meta_info, msg = await self.app.express_interest(
                    msg_int_name, int_param=int_param)
                break
            except InterestNack as e:
                logging.debug(f'Nacked with reason: {e.reason}')
                await aio.sleep(1)
                n_retries -= 1
            except InterestTimeout:
                logging.debug(f'Timeout')
                n_retries -= 1
        if msg == None:
            return

        # pass msg to application
        logging.info(f'received subscribed msg: {Name.to_str(msg_int_name)}')
        self.topic_to_cb[topic](bytes(msg))

        # acknowledge notify interest with an empty data packet
        logging.debug(f'acknowledging notify interest {Name.to_str(int_name)}')
        self.app.put_data(int_name, None)
예제 #10
0
    def test_default():
        name = Name.from_str('/local/ndn/prefix')
        interest = make_interest(name, InterestParam())
        assert interest == b'\x05\x1a\x07\x14\x08\x05local\x08\x03ndn\x08\x06prefix\x0c\x02\x0f\xa0'

        name = Name.encode(name)
        interest = make_interest(name, InterestParam())
        assert interest == b'\x05\x1a\x07\x14\x08\x05local\x08\x03ndn\x08\x06prefix\x0c\x02\x0f\xa0'

        name = '/local/ndn/prefix'
        interest = make_interest(name, InterestParam())
        assert interest == b'\x05\x1a\x07\x14\x08\x05local\x08\x03ndn\x08\x06prefix\x0c\x02\x0f\xa0'
예제 #11
0
 def test_forwarding_hint():
     name = '/local/ndn/prefix'
     int_param = InterestParam()
     int_param.nonce = 0x01020304
     int_param.forwarding_hint = [(0x87, '/name/A'),
                                  (0x02, Name.from_str('/ndn/B')),
                                  (0x12, b'\x07\x0d\x08\x0bshekkuenseu')]
     interest = make_interest(name, int_param)
     assert (interest ==
             b'\x05\x55\x07\x14\x08\x05local\x08\x03ndn\x08\x06prefix'
             b'\x1e\x33'
             b'\x1f\x0e\x1e\x01\x87\x07\x09\x08\x04name\x08\x01A'
             b'\x1f\x0d\x1e\x01\x02\x07\x08\x08\x03ndn\x08\x01B'
             b'\x1f\x12\x1e\x01\x12\x07\r\x08\x0bshekkuenseu'
             b'\x0a\x04\x01\x02\x03\x04\x0c\x02\x0f\xa0')
예제 #12
0
 def test2():
     interest = make_interest(
         '/localhost/nfd/faces/events',
         InterestParam(must_be_fresh=True, can_be_prefix=True))
     lp_packet = make_network_nack(interest, NackReason.NO_ROUTE)
     assert lp_packet == (
         b"\x64\x36\xfd\x03\x20\x05\xfd\x03\x21\x01\x96"
         b"\x50\x2b\x05\x29\x07\x1f\x08\tlocalhost\x08\x03nfd\x08\x05faces\x08\x06events"
         b"\x21\x00\x12\x00\x0c\x02\x0f\xa0")
    async def _process_notify_interest(self, int_name, int_param, app_param):
        """
        Async helper for ``_on_notify_interest()``.
        """
        logging.debug(f'received notify interest: {Name.to_str(int_name)}')
        topic = int_name[:-2]  # remove digest and `notify`

        # parse notify interest
        app_param = PubSub.NotifyAppParam.parse(app_param)
        publisher_prefix = app_param.publisher_prefix
        nonce = app_param.nonce
        publisher_fwd_hint = app_param.publisher_fwd_hint
        int_param = InterestParam()
        if publisher_fwd_hint:
            int_param.forwarding_hint = publisher_fwd_hint

        # send msg interest, retransmit 3 times
        msg_int_name = publisher_prefix + ['msg', str(nonce)]
        n_retries = 3
        while n_retries > 0:
            try:
                logging.debug(
                    f'sending msg interest: {Name.to_str(msg_int_name)}')
                data_name, meta_info, msg = await self.app.express_interest(
                    msg_int_name, int_param=int_param)
                break
            except InterestNack as e:
                logging.debug(f'Nacked with reason: {e.reason}')
                await aio.sleep(1)
            except InterestTimeout:
                logging.debug(f'Timeout')
        if msg == None:
            return

        # pass msg to application
        logging.info(f'received subscribed msg: {Name.to_str(msg_int_name)}')
        self.topic_to_cb[topic](bytes(msg))

        # acknowledge notify interest with an empty data packet
        logging.debug(f'acknowledging notify interest {Name.to_str(int_name)}')
        self.app.put_data(int_name, None)
예제 #14
0
 def test_interest_params():
     name = '/local/ndn/prefix'
     int_param = InterestParam()
     int_param.can_be_prefix = True
     int_param.must_be_fresh = True
     int_param.hop_limit = 1
     int_param.nonce = 0
     int_param.lifetime = 10
     interest = make_interest(name, int_param)
     assert (interest == b'\x05\x26\x07\x14\x08\x05local\x08\x03ndn\x08\x06prefix'
                         b'\x21\x00\x12\x00\x0a\x04\x00\x00\x00\x00\x0c\x01\x0a\x22\x01\x01')
예제 #15
0
 def make_pubunadv_cmd(self,
                       prefix,
                       dataname,
                       pubadvinfo: PubAdvInfo = None) -> (str, Any):
     """
     make pubunadv command
     :param prefix: network_prefix or broker_prefix
     :type prefix: str
     :param dataname: dataname for unpublishing data
     :type dataname: str
     :param pubadvinfo: pub information
     :type pubadvinfo: 
     :return: command, interest_param, app_param
     """
     # make a pubunadv command name with args
     command = prefix + "/" + PSKCmd.commands["CMD_PU"] + dataname
     # set interest parameter
     i_param = InterestParam()
     i_param.must_be_fresh = True
     i_param.nonce = gen_nonce()
     i_param.lifetime = INT_LT_10
     param = PSKParameters(pubadvinfo=pubadvinfo)
     str_app_param = json.dumps(param, default=serialize)
     return command, i_param, bytes(str_app_param, 'utf-8')
예제 #16
0
    def test_throws():
        with pytest.raises(ValueError):
            make_interest("/invalid%%name", InterestParam())

        with pytest.raises(TypeError):
            make_interest("/ndn", InterestParam(lifetime=0.5))

        with pytest.raises(TypeError):
            make_interest("/ndn", InterestParam(forwarding_hint=[1, 2, 3]))

        with pytest.raises(ValueError):
            make_interest("/ndn", InterestParam(hop_limit=300))

        with pytest.raises(ValueError):
            make_interest("/params-sha256=4077", InterestParam())

        with pytest.raises(ValueError):
            make_interest("/params-sha256=4077", InterestParam(), b'')
예제 #17
0
from dataclasses_json import dataclass_json
from flask import Flask, Response, request
from ndn.encoding import InterestParam, make_interest
from ndn.encoding.name import Name
from ndn.encoding.ndn_format_0_3 import parse_data

from h3client import H3Client

app = Flask(__name__)

ORIGIN = "https://health.ndn-quic-gateway.invalid"
MTU = 1200
CONNECT_TIMEOUT = 2.0
INTEREST_TIMEOUT = 4.0
INTEREST_TIMEOUT_STEP = 0.05
INTEREST_PARAMS = InterestParam(must_be_fresh=True, hop_limit=64)


@dataclass
class ProbeNameResult:
    ok: bool
    rtt: T.Optional[float] = None
    error: T.Optional[str] = None


@dataclass_json
@dataclass
class ProbeResult:
    connected: bool = False
    connectError: T.Optional[str] = None
    probes: T.Optional[T.List[ProbeNameResult]] = None
예제 #18
0
 def test_mixed_name():
     name = ['local', Component.from_str('ndn'), 'prefix']
     interest = make_interest(name, InterestParam())
     assert interest == b'\x05\x1a\x07\x14\x08\x05local\x08\x03ndn\x08\x06prefix\x0c\x02\x0f\xa0'
예제 #19
0
    def express_interest(
        self,
        name: NonStrictName,
        app_param: Optional[BinaryStr] = None,
        validator: Optional[Validator] = None,
        need_raw_packet: bool = False,
        **kwargs
    ) -> Coroutine[Any, None, Tuple[FormalName, MetaInfo,
                                    Optional[BinaryStr]]]:
        r"""
        Express an Interest packet.

        The Interest packet is sent immediately and a coroutine used to get the result is returned.
        Awaiting on what is returned will block until the Data is received and return that Data.
        An exception is raised if unable to receive the Data.

        :param name: the Name.
        :type name: :any:`NonStrictName`
        :param app_param: the ApplicationParameters.
        :type app_param: Optional[:any:`BinaryStr`]
        :param validator: the Validator used to verify the Data received.
        :type validator: Optional[:any:`Validator`]
        :param need_raw_packet: if True, return the raw Data packet with TL.
        :type need_raw_packet: bool
        :param kwargs: :ref:`label-keyword-arguments`.
        :return: A tuple of (Name, MetaInfo, Content) after ``await``.
            If need_raw_packet is True, return a tuple (Name, MetaInfo, Content, RawPacket).
        :rtype: Coroutine[Any, None, Tuple[:any:`FormalName`, :any:`MetaInfo`, Optional[:any:`BinaryStr`]]]

        The following exception is raised by ``express_interest``:

        :raises NetworkError: the face to NFD is down before sending this Interest.

        The following exceptions are raised by the coroutine returned:

        :raises InterestNack: an NetworkNack is received.
        :raises InterestTimeout: time out.
        :raises ValidationFailure: unable to validate the Data packet.
        :raises InterestCanceled: the face to NFD is shut down after sending this Interest.
        """
        if not self.face.running:
            raise NetworkError('cannot send packet before connected')
        if 'signer' in kwargs:
            signer = kwargs['signer']
        elif app_param is not None:
            signer = self.keychain.get_signer(kwargs)
        else:
            signer = None
        if 'interest_param' in kwargs:
            interest_param = kwargs['interest_param']
        else:
            if 'nonce' not in kwargs:
                kwargs['nonce'] = gen_nonce()
            interest_param = InterestParam.from_dict(kwargs)
        interest, final_name = make_interest(name,
                                             interest_param,
                                             app_param,
                                             signer=signer,
                                             need_final_name=True)
        future = aio.get_event_loop().create_future()
        node = self._int_tree.setdefault(final_name, InterestTreeNode())
        node.append_interest(future, interest_param)
        self.face.send(interest)
        return self._wait_for_data(future, interest_param.lifetime, final_name,
                                   node, validator, need_raw_packet)