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')
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'
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')
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')
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')
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')
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')
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')
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')
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 = 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)
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')
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')
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)
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'')
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')
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'
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