def onVerifiedAppRequest(interest): # TODO: for now, we automatically grant access to any valid signed interest print("verified! send response!") message = AppRequestMessage() ProtobufTlv.decode( message, interest.getName().get(prefix.size() + 1).getValue()) certName = Name("/".join(message.command.idName.components)) dataPrefix = Name("/".join( message.command.dataPrefix.components)) appName = message.command.appName isUpdated = self.updateTrustSchema(appName, certName, dataPrefix, True) response = Data(interest.getName()) if isUpdated: response.setContent( "{\"status\": 200, \"message\": \"granted, trust schema updated OK\" }" ) self.log.info( "Verified and granted application publish request") else: response.setContent( "{\"status\": 400, \"message\": \"not granted, requested publishing namespace already exists\" }" ) self.log.info( "Verified and but requested namespace already exists") self.sendData(response) return
def processCreateFaceResponse(encodedControlResponse, prefix, face, enabled): """ This is called when the face create command responds to decode the encodedControlResonse as a TLV ControlResponse message containing one ControlParameters. Get the face ID and call registerRoute(). :param Blob encodedControlResponse: The TLV-encoded ControlResponse. """ decodedControlResponse = \ control_parameters_pb2.ControlParametersTypes.ControlParametersResponseMessage() ProtobufTlv.decode(decodedControlResponse, encodedControlResponse) controlResponse = decodedControlResponse.control_response lowestErrorCode = 400 if controlResponse.status_code >= lowestErrorCode: dump("Face create command got error, code " + str(controlResponse.status_code) + ": " + controlResponse.status_text) enabled[0] = False return if len(controlResponse.control_parameters) != 1: dump( "Face create command response does not have one ControlParameters") enabled[0] = False return faceId = controlResponse.control_parameters[0].face_id dump("Created face ID " + str(faceId)) registerRoute(prefix, faceId, face, enabled)
def printFaceStatuses(self, encodedMessage): """ This is called when all the segments are received to decode the encodedMessage repeated TLV FaceStatus messages and display the values. :param Blob encodedMessage: The repeated TLV-encoded FaceStatus. """ faceStatusMessage = face_status_pb2.FaceStatusMessage() ProtobufTlv.decode(faceStatusMessage, encodedMessage) self.dump("Faces:") for faceStatus in faceStatusMessage.face_status: '''ignore those on-demand faces created by APPs, especially this node.py APP''' if (faceStatus.local_uri == 'tcp4://127.0.0.1:6363' and \ faceStatus.face_scope == 1 and \ faceStatus.face_persistency == 1 and \ faceStatus.link_type != 1): continue line = "" # Format to look the same as "nfd-status -f". line += (" faceid=" + str(faceStatus.face_id) + " remote=" + faceStatus.uri + " local=" + faceStatus.local_uri) line += (" " + ("local" if faceStatus.face_scope == 1 else "non-local") + " " + ("permanent" if faceStatus.face_persistency == 2 else ("on-demand" if faceStatus.face_persistency == 1 else "persistent")) + " " + ("multi-access" if faceStatus.link_type == 1 else "point-to-point")) self.dump(line)
def printRibEntries(encodedMessage): """ This is called when all the segments are received to decode the encodedMessage as repeated TLV RibEntry messages and display the values. :param Blob encodedMessage: The repeated TLV-encoded RibEntry. """ ribEntryMessage = rib_entry_pb2.RibEntryMessage() ProtobufTlv.decode(ribEntryMessage, encodedMessage) dump("RIB:"); for ribEntry in ribEntryMessage.rib_entry: line = "" for component in ribEntry.name.component: # component may be a bytes type, so use Blob to convert to str. line += "/" + Blob(component, False).toRawStr() # Show the routes. for route in ribEntry.routes: line += (" route={faceId=" + str(route.face_id) + " (origin=" + str(route.origin) + " cost=" + str(route.cost)) if (route.flags & 1) != 0: line += " ChildInherit" if (route.flags & 2) != 0: line += " Capture" if route.HasField("expiration_period"): line += " expirationPeriod=" + str(route.expiration_period) line += ")}" dump(line)
def general_status(): def convert_time(timestamp): ret = datetime.fromtimestamp(float(timestamp) / 1000.0) return str(ret) interest = Interest("/localhost/nfd/status/general") interest.mustBeFresh = True interest.canBePrefix = True ret = run_until_complete(fetch_data_packet(server.face, interest)) if isinstance(ret, Data): name = ret.name.toUri() msg = GeneralStatus() try: ProtobufTlv.decode(msg, ret.content) except RuntimeError as exc: logging.fatal("Decoding Error %s", exc) return "Decoding Error" status = decode_dict(msg) status['start_timestamp'] = convert_time(status['start_timestamp']) status['current_timestamp'] = convert_time( status['current_timestamp']) return render_template('general-status.html', refer_name='/general-status', name=name, status=status) else: logging.info("No response: general status") return redirect('/')
def main(): # Construct a sample FibEntry message using the structure in fib_entry_pb2 # which was produced by protoc. message = fib_entry_pb2.FibEntryMessage() message.fib_entry.name.component.append("ndn") message.fib_entry.name.component.append("ucla") nextHopRecord = message.fib_entry.next_hop_records.add() nextHopRecord.face_id = 16 nextHopRecord.cost = 1 # Encode the Protobuf message object as TLV. encoding = ProtobufTlv.encode(message) decodedMessage = fib_entry_pb2.FibEntryMessage() ProtobufTlv.decode(decodedMessage, encoding) dump("Re-decoded FibEntry:") # This should print the same values that we put in message above. value = "" for component in decodedMessage.fib_entry.name.component: value += "/" + component value += " nexthops = {" for next_hop_record in decodedMessage.fib_entry.next_hop_records: value += ("faceid=" + repr(next_hop_record.face_id) + " (cost=" + repr(next_hop_record.cost) + ")") value += " }" dump(value)
def _onConfigurationReceived(self, prefix, interest, transport, prefixId): # the interest we get here is signed by HMAC, let's verify it self.tempPrefixId = prefixId # didn't get it from register because of the event loop interestName = interest.getName() replyData = Data(interestName) if len(interestName) == len(prefix): # this is a discovery request. Check the exclude to see if we should # return our serial serial = self.getSerial() serialComponent = Name.Component(serial) if not interest.getExclude().matches(serialComponent): replyData.setContent(serial) self.sendData(replyData, transport, False) # no point in signing elif (self._hmacHandler.verifyInterest(interest)): # we have a match! decode the network parameters configComponent = interest.getName()[len(prefix)+1] replyData.setContent('200') self._hmacHandler.signData(replyData, keyName=self.prefix) transport.send(replyData.wireEncode().buf()) environmentConfig = DeviceConfigurationMessage() ProtobufTlv.decode(environmentConfig, configComponent.getValue()) networkPrefix = self._extractNameFromField(environmentConfig.configuration.networkPrefix) controllerName = self._extractNameFromField(environmentConfig.configuration.controllerName) controllerName = Name(networkPrefix).append(controllerName) self._policyManager.setEnvironmentPrefix(networkPrefix) self._policyManager.setTrustRootIdentity(controllerName) self.deviceSuffix = self._extractNameFromField(environmentConfig.configuration.deviceSuffix) self._configureIdentity = Name(networkPrefix).append(self.deviceSuffix) self._sendCertificateRequest(self._configureIdentity)
def face_list(): interest = Interest("/localhost/nfd/faces/list") interest.mustBeFresh = True interest.canBePrefix = True ret = run_until_complete(fetch_data_packet(server.face, interest)) if isinstance(ret, Data): name = ret.name.toUri() msg = FaceStatusMessage() try: ProtobufTlv.decode(msg, ret.content) except RuntimeError as exc: logging.fatal("Decoding Error %s", exc) return "Decoding Error" face_list = decode_list(msg.face_status) fields = list(face_list[0].keys()) fields_collapse = [ field for field in set(fields) - {'face_id', 'uri'} ] return render_template('face-list.html', refer_name='/face-list', face_list=face_list, fields_collapse=fields_collapse, **request.args.to_dict()) else: logging.info("No response: face-list") return redirect('/')
def controlTV(self): count = 0 for pir in self.getPirs(): if pir.status.getLastValue(): count += 1 if count >= 2: # TODO: Send command interest to TV self.log.info("turn on tv") for cec in self.getCecs(): message = pb.CommandMessage() message.destination = pb.TV message.commands.append(pb.AS) message.commands.append(pb.SLEEP) message.commands.append(pb.PLAY) encodedMessage = ProtobufTlv.encode(message) interest = Interest(Name(cec.id).append(encodedMessage)) # self.face.makeCommandInterest(interest) self.face.expressInterest(interest, self.onDataCec, self.onTimeoutCec) elif count == 0: # TODO: Send command interest to TV self.log.info("turn off tv") for cec in self.getCecs(): message = pb.CommandMessage() message.destination = pb.TV message.commands.append(pb.STANDBY) encodedMessage = ProtobufTlv.encode(message) interest = Interest(Name(cec.id).append(encodedMessage)) # self.face.makeCommandInterest(interest) self.face.expressInterest(interest, self.onDataCec, self.onTimeoutCec)
def route_list(): def decode_route_list(msg): ret = [] for item in msg: name = decode_name(item.name) routes = decode_list(item.route) ret.append((name, routes)) return ret interest = Interest("/localhost/nfd/rib/list") interest.mustBeFresh = True interest.canBePrefix = True ret = run_until_complete(fetch_data_packet(server.face, interest)) if isinstance(ret, Data): name = ret.name.toUri() msg = RibStatusMessage() try: ProtobufTlv.decode(msg, ret.content) except RuntimeError as exc: logging.fatal("Decoding Error %s", exc) return "Decoding Error" rib_list = decode_route_list(msg.rib_entry) return render_template('route-list.html', refer_name='/route-list', rib_list=rib_list, **request.args.to_dict()) else: logging.info("No response: route-list") return redirect('/')
def printRibEntries(encodedMessage): """ This is called when all the segments are received to decode the encodedMessage as repeated TLV RibEntry messages and display the values. :param Blob encodedMessage: The repeated TLV-encoded RibEntry. """ ribEntryMessage = rib_entry_pb2.RibEntryMessage() ProtobufTlv.decode(ribEntryMessage, encodedMessage) dump("RIB:"); for ribEntry in ribEntryMessage.rib_entry: line = "" line += ProtobufTlv.toName(ribEntry.name.component).toUri() # Show the routes. for route in ribEntry.routes: line += (" route={faceId=" + str(route.face_id) + " (origin=" + str(route.origin) + " cost=" + str(route.cost)) if (route.flags & 1) != 0: line += " ChildInherit" if (route.flags & 2) != 0: line += " Capture" if route.HasField("expiration_period"): line += " expirationPeriod=" + str(route.expiration_period) line += ")}" dump(line)
def printFaceStatuses(encodedMessage): """ This is called when all the segments are received to decode the encodedMessage repeated TLV FaceStatus messages and display the values. :param Blob encodedMessage: The repeated TLV-encoded FaceStatus. """ faceStatusMessage = face_status_pb2.FaceStatusMessage() ProtobufTlv.decode(faceStatusMessage, encodedMessage) dump("Faces:"); for faceStatus in faceStatusMessage.face_status: line = "" # Format to look the same as "nfd-status -f". line += (" faceid=" + str(faceStatus.face_id) + " remote=" + faceStatus.uri + " local=" + faceStatus.local_uri) if faceStatus.HasField("expiration_period"): # Convert milliseconds to seconds. line += (" expires=" + str(round(faceStatus.expiration_period / 1000.0)) + "s") line += (" counters={" + "in={" + str(faceStatus.n_in_interests) + "i " + str(faceStatus.n_in_datas) + "d " + str(faceStatus.n_in_bytes) + "B}" + " out={" + str(faceStatus.n_out_interests) + "i "+ str(faceStatus.n_out_datas) + "d " + str(faceStatus.n_out_bytes) + "B}" + "}" + " " + ("local" if faceStatus.face_scope == 1 else "non-local") + " " + ("permanent" if faceStatus.face_persistency == 2 else ("on-demand" if faceStatus.face_persistency == 1 else "persistent")) + " " + ("multi-access" if faceStatus.link_type == 1 else "point-to-point")) dump(line)
def _onConfigurationReceived(self, prefix, interest, face, interestFilterId, filter): # the interest we get here is signed by HMAC, let's verify it self.tempPrefixId = interestFilterId # didn't get it from register because of the event loop dataName = Name(interest.getName()) replyData = Data(dataName) if (self._hmacHandler.verifyInterest(interest)): # we have a match! decode the controller's name configComponent = interest.getName().get(prefix.size()) replyData.setContent('200') self._hmacHandler.signData(replyData, keyName=self.prefix) self.face.putData(replyData) environmentConfig = DeviceConfigurationMessage() ProtobufTlv.decode(environmentConfig, configComponent.getValue()) networkPrefix = self._extractNameFromField( environmentConfig.configuration.networkPrefix) controllerName = self._extractNameFromField( environmentConfig.configuration.controllerName) controllerName = Name(networkPrefix).append(controllerName) self._policyManager.setEnvironmentPrefix(networkPrefix) self._policyManager.setTrustRootIdentity(controllerName) self.deviceSuffix = self._extractNameFromField( environmentConfig.configuration.deviceSuffix) self._configureIdentity = Name(networkPrefix).append( self.deviceSuffix) self._sendCertificateRequest(self._configureIdentity)
def _onConfigurationReceived(self, prefix, interest, transport, prefixId): # the interest we get here is signed by HMAC, let's verify it self.tempPrefixId = prefixId # didn't get it from register because of the event loop dataName = Name(interest.getName()) replyData = Data(dataName) if (self._hmacHandler.verifyInterest(interest)): # we have a match! decode the controller's name configComponent = interest.getName().get(prefix.size()) replyData.setContent('200') self._hmacHandler.signData(replyData, keyName=self.prefix) transport.send(replyData.wireEncode().buf()) environmentConfig = DeviceConfigurationMessage() ProtobufTlv.decode(environmentConfig, configComponent.getValue()) networkPrefix = self._extractNameFromField(environmentConfig.configuration.networkPrefix) controllerName = self._extractNameFromField(environmentConfig.configuration.controllerName) controllerName = Name(networkPrefix).append(controllerName) self._policyManager.setEnvironmentPrefix(networkPrefix) self._policyManager.setTrustRootIdentity(controllerName) self.deviceSuffix = self._extractNameFromField(environmentConfig.configuration.deviceSuffix) self._configureIdentity = Name(networkPrefix).append(self.deviceSuffix) self._sendCertificateRequest(self._configureIdentity)
def main(): # Construct a sample FibEntry message using the structure in fib_entry_pb2 # which was produced by protoc. message = fib_entry_pb2.FibEntryMessage() message.fib_entry.name.component.append(b"ndn") message.fib_entry.name.component.append(b"ucla") nextHopRecord = message.fib_entry.next_hop_records.add() nextHopRecord.face_id = 16 nextHopRecord.cost = 1 # Encode the Protobuf message object as TLV. encoding = ProtobufTlv.encode(message) decodedMessage = fib_entry_pb2.FibEntryMessage() ProtobufTlv.decode(decodedMessage, encoding) dump("Re-decoded FibEntry:") # This should print the same values that we put in message above. value = "" value += ProtobufTlv.toName( decodedMessage.fib_entry.name.component).toUri() value += " nexthops = {" for next_hop_record in decodedMessage.fib_entry.next_hop_records: value += ("faceid=" + repr(next_hop_record.face_id) + " (cost=" + repr(next_hop_record.cost) + ")") value += " }" dump(value)
def processCreateFaceResponse(encodedControlResponse, prefix, face, enabled): """ This is called when the face create command responds to decode the encodedControlResonse as a TLV ControlResponse message containing one ControlParameters. Get the face ID and call registerRoute(). :param Blob encodedControlResponse: The TLV-encoded ControlResponse. """ decodedControlResponse = \ control_parameters_pb2.ControlParametersTypes.ControlParametersResponseMessage() ProtobufTlv.decode(decodedControlResponse, encodedControlResponse) controlResponse = decodedControlResponse.control_response lowestErrorCode = 400 if controlResponse.status_code >= lowestErrorCode: dump( "Face create command got error, code " + str(controlResponse.status_code) + ": " + controlResponse.status_text) enabled[0] = False return if len(controlResponse.control_parameters) != 1: dump( "Face create command response does not have one ControlParameters") enabled[0] = False return faceId = controlResponse.control_parameters[0].face_id dump("Created face ID " + str(faceId)) registerRoute(prefix, faceId, face, enabled)
def onLightingCommand(self, prefix, interest, transport, prefixId): interestName = Name(interest.getName()) #d = Data(interest.getName().getPrefix(prefix.size()+1)) d = Data(interest.getName()) # get the command parameters from the name try: commandComponent = interest.getName().get(prefix.size()) commandParams = interest.getName().get(prefix.size()+1) lightingCommand = LightCommandMessage() ProtobufTlv.decode(lightingCommand, commandParams.getValue()) self.log.info("Command: " + commandComponent.toEscapedString()) requestedColor = lightingCommand.command.pattern.colors[0] colorStr = str((requestedColor.r, requestedColor.g, requestedColor.b)) self.log.info("Requested color: " + colorStr) self.setPayloadColor(0, requestedColor) self.sendLightPayload(1) d.setContent("Gotcha: " + colorStr+ "\n") except Exception as e: print e d.setContent("Bad command\n") finally: d.getMetaInfo().setFinalBlockID(0) self.signData(d) encodedData = d.wireEncode() transport.send(encodedData.toBuffer())
async def send_cmd_interest(self): event_loop = asyncio.get_event_loop() face_task = event_loop.create_task(self.face_loop()) parameter = RepoCommandParameterMessage() for compo in self.prefix: parameter.repo_command_parameter.name.component.append(compo.getValue().toBytes()) parameter.repo_command_parameter.start_block_id = self.latest_tp parameter.repo_command_parameter.end_block_id = parameter.repo_command_parameter.start_block_id param_blob = ProtobufTlv.encode(parameter) # Prepare cmd interest name = Name(self.repo_name).append("insert").append(Name.Component(param_blob)) interest = Interest(name) interest.canBePrefix = True self.face.makeCommandInterest(interest) logging.info("Express interest: {}".format(interest.getName())) ret = await fetch_data_packet(self.face, interest) if not isinstance(ret, Data): logging.warning("Insertion failed") else: # Parse response response = RepoCommandResponseMessage() try: ProtobufTlv.decode(response, ret.content) logging.info('Insertion command accepted: status code {}' .format(response.repo_command_response.status_code)) except RuntimeError as exc: logging.warning('Response decoding failed', exc)
def strategy_list(): def decode_strategy(msg): return [{ "name": decode_name(item.name), "strategy": decode_name(item.strategy.name), } for item in msg] interest = Interest("/localhost/nfd/strategy-choice/list") interest.mustBeFresh = True interest.canBePrefix = True ret = run_until_complete(fetch_data_packet(server.face, interest)) if isinstance(ret, Data): msg = StrategyChoiceMessage() try: ProtobufTlv.decode(msg, ret.content) except RuntimeError as exc: logging.info("Decoding Error %s", exc) return "Decoding Error" strategy_list = decode_strategy(msg.strategy_choice) return render_template('strategy-list.html', refer_name='/strategy-list', strategy_list=strategy_list, **request.args.to_dict()) else: logging.info("No response: strategy-list") return redirect('/')
def processRegisterResponse(encodedControlResponse): """ This is called when the register route command responds to decode the encodedControlResponse as a TLV ControlParametersResponse message containing one ControlParameters. On success, print the ControlParameters values which should be the same as requested. :param Blob encodedControlResponse: The TLV-encoded ControlParametersResponse. """ decodedControlResponse = \ control_parameters_pb2.ControlParametersTypes.ControlParametersResponseMessage() ProtobufTlv.decode(decodedControlResponse, encodedControlResponse) controlResponse = decodedControlResponse.control_response lowestErrorCode = 400 if controlResponse.status_code >= lowestErrorCode: dump( "Face create command got error, code " + str(controlResponse.status_code) + ": " + controlResponse.status_text) return if len(controlResponse.control_parameters) != 1: dump( "Face create command response does not have one ControlParameters") return # Success. Print the ControlParameters response. controlParameters = controlResponse.control_parameters[0] dump( "Successful in name registration: ControlParameters(Name: " + ProtobufTlv.toName(controlParameters.name.component).toUri() + ", FaceId: " + str(controlParameters.face_id) + ", Origin: " + str(controlParameters.origin) + ", Cost: " + str(controlParameters.cost) + ", Flags: " + str(controlParameters.flags) + ")")
def processRegisterResponse(encodedControlResponse): """ This is called when the register route command responds to decode the encodedControlResponse as a TLV ControlParametersResponse message containing one ControlParameters. On success, print the ControlParameters values which should be the same as requested. :param Blob encodedControlResponse: The TLV-encoded ControlParametersResponse. """ decodedControlResponse = \ control_parameters_pb2.ControlParametersTypes.ControlParametersResponseMessage() ProtobufTlv.decode(decodedControlResponse, encodedControlResponse) controlResponse = decodedControlResponse.control_response lowestErrorCode = 400 if controlResponse.status_code >= lowestErrorCode: dump("Face create command got error, code " + str(controlResponse.status_code) + ": " + controlResponse.status_text) return if len(controlResponse.control_parameters) != 1: dump( "Face create command response does not have one ControlParameters") return # Success. Print the ControlParameters response. controlParameters = controlResponse.control_parameters[0] dump("Successful in name registration: ControlParameters(Name: " + ProtobufTlv.toName(controlParameters.name.component).toUri() + ", FaceId: " + str(controlParameters.face_id) + ", Origin: " + str(controlParameters.origin) + ", Cost: " + str(controlParameters.cost) + ", Flags: " + str(controlParameters.flags) + ")")
def versionFromCommandMessage(self, component): command = RepoCommandParameterMessage() try: ProtobufTlv.decode(command, component.getValue()) except Exception as e: logger.warn(e) # last component of name to insert is version versionStr = command.repo_command_parameter.name.component[-1] return versionStr
def onCecCommand(self, interest): self.log.debug("Received CEC command") # check command interest name # verify command interest message = pb.CommandMessage() ProtobufTlv.decode(message, interest.getName().get(3).getValue()) self.loop.call_soon(self.processCommands, message) data = Data(interest.getName()) data.setContent('ACK') return data
def onCommandData(interest, data): global current_insertion # global current_status now = time.time() # assume it's a command response response = RepoCommandResponseMessage() ProtobufTlv.decode(response, data.getContent()) current_status = response.repo_command_response.status_code current_insertion = response.repo_command_response.process_id logger.debug("Response status code: " + str(current_status) + ", process id: " + str(current_insertion) + ", insert #" + str(response.repo_command_response.insert_num))
def decode_cmd_response_blob(data: Data) -> RepoCommandResponseMessage: """ Decode the command response and return a RepoCommandResponseMessage object. Throw RuntimeError on decoding failure. """ response = RepoCommandResponseMessage() response_blob = data.getContent() try: ProtobufTlv.decode(response, response_blob) except RuntimeError as exc: raise exc return response
async def run(self, repo_name: str, prefix: str, start_block_id: int, end_block_id: int): """ Send a delete command to remove all the data within [start_block_id, end_block_id]. """ # Send command interest prefix = Name(prefix) parameter = RepoCommandParameterMessage() for compo in prefix: parameter.repo_command_parameter.name.component.append( compo.getValue().toBytes()) parameter.repo_command_parameter.start_block_id = start_block_id parameter.repo_command_parameter.end_block_id = end_block_id param_blob = ProtobufTlv.encode(parameter) name = Name(repo_name).append('delete').append( Name.Component(param_blob)) interest = Interest(name) self.face.makeCommandInterest(interest) logging.info('Send delete command interest') ret = await fetch_data_packet(self.face, interest) # Parse response if not isinstance(ret, Data): logging.warning('Delete error') return response = RepoCommandResponseMessage() try: ProtobufTlv.decode(response, ret.content) except RuntimeError as exc: logging.warning('Response decoding failed', exc) process_id = response.repo_command_response.process_id status_code = response.repo_command_response.status_code logging.info('Delete process {} accepted, status {}'.format( process_id, status_code)) # Use delete check command to probe if delete process is completed checker = CommandChecker(self.face, self.keychain) while True: response = await checker.check_delete(repo_name, process_id) if response.repo_command_response.status_code == 300: await asyncio.sleep(1) elif response.repo_command_response.status_code == 200: logging.info( 'Delete process {} status: {}, delete_num: {}'.format( process_id, response.repo_command_response.status_code, response.repo_command_response.delete_num)) break else: # Shouldn't get here assert (False)
async def insert_segmented_file(self): event_loop = asyncio.get_event_loop() face_task = event_loop.create_task(self.face_loop()) parameter = RepoCommandParameterMessage() for compo in self.name_at_repo: parameter.repo_command_parameter.name.component.append( compo.getValue().toBytes()) parameter.repo_command_parameter.start_block_id = 0 parameter.repo_command_parameter.end_block_id = self.n_packets - 1 param_blob = ProtobufTlv.encode(parameter) # Prepare cmd interest name = Name(self.repo_name).append('insert').append( Name.Component(param_blob)) interest = Interest(name) self.face.makeCommandInterest(interest) logging.info('Send insert command interest') ret = await fetch_data_packet(self.face, interest) if not isinstance(ret, Data): logging.warning('Insert failed') return response = RepoCommandResponseMessage() try: ProtobufTlv.decode(response, ret.content) except RuntimeError as exc: logging.warning('Response decoding failed', exc) process_id = response.repo_command_response.process_id status_code = response.repo_command_response.status_code logging.info('Insertion process {} accepted: status code {}'.format( process_id, status_code)) # Use insert check command to probe if insert process is completed checker = CommandChecker(self.face, self.keychain) while True: response = await checker.check_insert(self.repo_name, process_id) if response is None or response.repo_command_response.status_code == 300: await asyncio.sleep(1) elif response.repo_command_response.status_code == 200: logging.info( 'Insert process {} status: {}, insert_num: {}'.format( process_id, response.repo_command_response.status_code, response.repo_command_response.insert_num)) break else: # Shouldn't get here assert (False) self.running = False await face_task
async def issue_command_interest(self, interest): ret = await fetch_data_packet(self.face, interest) if isinstance(ret, Data): response = ControlResponseMessage() try: ProtobufTlv.decode(response, ret.content) dic = self.response_to_dict(response.control_response) logging.info("Issue command Interest with %s", dic) return dic except RuntimeError as exc: logging.fatal('Decode failed %s', exc) return None
def onRepoCommandResponse(interest, data): # repo_command_response_pb2 was produced by protoc. response = repo_command_response_pb2.RepoCommandResponseMessage() try: ProtobufTlv.decode(response, data.content) except: print("Cannot decode the repo command response") if response.repo_command_response.status_code == 100: if __debug__: print("Insertion started") else: print("Got repo command error code", response.repo_command_response.status_code)
def printChannelStatuses(encodedMessage): """ This is called when all the segments are received to decode the encodedMessage repeated TLV ChannelStatus messages and display the values. :param Blob encodedMessage: The repeated TLV-encoded ChannelStatus. """ channelStatusMessage = channel_status_pb2.ChannelStatusMessage() ProtobufTlv.decode(channelStatusMessage, encodedMessage) dump("Channels:"); for channelStatus in channelStatusMessage.channel_status: # Format to look the same as "nfd-status -c". dump(" " + channelStatus.local_uri)
def printChannelStatuses(self, encodedMessage): """ This is called when all the segments are received to decode the encodedMessage repeated TLV ChannelStatus messages and display the values. :param Blob encodedMessage: The repeated TLV-encoded ChannelStatus. """ channelStatusMessage = channel_status_pb2.ChannelStatusMessage() ProtobufTlv.decode(channelStatusMessage, encodedMessage) self.dump("Channels:") for channelStatus in channelStatusMessage.channel_status: # Format to look the same as "nfd-status -c". self.dump(" " + channelStatus.local_uri)
async def face_event(self): last_seq = -1 retry_time = 3000 retry_count_limit = 60000 // retry_time retry_count = 0 while self.running and self.face: name = Name("/localhost/nfd/faces/events") face_interest = Interest() if last_seq >= 0: name.appendSequenceNumber(last_seq + 1) face_interest.canBePrefix = False else: face_interest.mustBeFresh = True face_interest.canBePrefix = True logging.info("Face event notification stream %s", name.toUri()) face_interest.name = name # face_interest.interestLifetimeMilliseconds = 60000 face_interest.interestLifetimeMilliseconds = retry_time ret = await fetch_data_packet(self.face, face_interest) timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") if isinstance(ret, Data): retry_count = 0 last_seq = ret.name[-1].toSequenceNumber() face_event = FaceEventNotificationMessage() try: ProtobufTlv.decode(face_event, ret.content) dic = self.face_event_to_dict(face_event.face_event_notification) dic['seq'] = str(last_seq) dic['time'] = timestamp self.emit('face event', dic) self.event_list.append(dic) except RuntimeError as exc: logging.fatal('Decode failed %s', exc) last_seq = -1 elif ret is None: if retry_count >= retry_count_limit: logging.info("No response: face event") last_seq = -1 retry_count = 0 else: retry_count += 1 else: logging.info("NFD is not running: start reconnection") self.start_reconnection() return await asyncio.sleep(0.1)
def onData(interest, data): # repo_command_response_pb2 was produced by protoc. response = repo_command_response_pb2.RepoCommandResponseMessage() try: ProtobufTlv.decode(response, data.content) except: dump("Cannot decode the repo command response") onFailed() if response.repo_command_response.status_code == 100: onInsertStarted() else: dump("Got repo command error code", response.repo_command_response.status_code) onFailed()
def requestInsert(face, repoCommandPrefix, fetchName, onInsertStarted, onFailed): # Construct a RepoCommandParameterMessage using the structure in # repo_command_parameter_pb2 which was produced by protoc. parameter = repo_command_parameter_pb2.RepoCommandParameterMessage() # Add the Name. msgName = parameter.Name() # 1. pattern name msgName.Clear() msgName.component.append(PATTERN_NAME[0].getValue().toBytes()) parameter.repo_command_parameter.name.component.append( ProtobufTlv.encode(msgName).toBytes()) # 2. fetch prefix msgName.Clear() for compo in fetchName: msgName.component.append(compo.getValue().toBytes()) parameter.repo_command_parameter.name.component.append( ProtobufTlv.encode(msgName).toBytes()) # Create the command interest. interest = Interest( Name(repoCommandPrefix).append("pattern").append( Name.Component(ProtobufTlv.encode(parameter)))) face.makeCommandInterest(interest) # Send the command interest and get the response or timeout. def onData(interest, data): # repo_command_response_pb2 was produced by protoc. response = repo_command_response_pb2.RepoCommandResponseMessage() try: ProtobufTlv.decode(response, data.content) except: dump("Cannot decode the repo command response") onFailed() if response.repo_command_response.status_code == 100: onInsertStarted() else: dump("Got repo command error code", response.repo_command_response.status_code) onFailed() def onTimeout(interest): dump("Pattern repo command timeout") onFailed() face.expressInterest(interest, onData, onTimeout)
def _beginPairing(self, encryptedMessage): # base64 decode, decrypt, protobuf decode responseCode = 202 try: encryptedBytes = base64.urlsafe_b64decode(str(encryptedMessage.getValue())) decryptedBytes = self._identityManager.decryptAsIdentity(encryptedBytes, self.prefix) message = DevicePairingInfoMessage() ProtobufTlv.decode(message, decryptedBytes) except: responseCode = 500 else: info = message.info self.loop.call_soon(self._addDeviceToNetwork, info.deviceSerial, info.deviceSuffix, info.devicePin) return responseCode
def _updateCapabilities(self): """ Send the controller a list of our commands. """ fullCommandName = Name( self._policyManager.getTrustRootIdentity()).append( 'updateCapabilities') capabilitiesMessage = UpdateCapabilitiesCommandMessage() for command in self._commands: commandName = Name(self.prefix).append(Name(command.suffix)) capability = capabilitiesMessage.capabilities.add() for i in range(commandName.size()): capability.commandPrefix.components.append( str(commandName.get(i).getValue())) for kw in command.keywords: capability.keywords.append(kw) capability.needsSignature = command.isSigned encodedCapabilities = ProtobufTlv.encode(capabilitiesMessage) fullCommandName.append(encodedCapabilities) interest = Interest(fullCommandName) interest.setInterestLifetimeMilliseconds(5000) self.face.makeCommandInterest(interest) signature = self._policyManager._extractSignature(interest) self.log.info("Sending capabilities to controller") self.face.expressInterest(interest, self._onCapabilitiesAck, self._onCapabilitiesTimeout) # update twice a minute self.loop.call_later(30, self._updateCapabilities)
def _sendCertificateRequest(self, keyIdentity): """ We compose a command interest with our public key info so the controller can sign us a certificate that can be used with other nodes in the network. """ #TODO: GENERATE A NEW PUBLIC/PRIVATE PAIR INSTEAD OF COPYING makeKey = False try: defaultKey = self._identityStorage.getDefaultKeyNameForIdentity( keyIdentity) newKeyName = defaultKey except SecurityException: defaultIdentity = self._keyChain.getDefaultIdentity() defaultKey = self._identityStorage.getDefaultKeyNameForIdentity( defaultIdentity) newKeyName = self._identityStorage.getNewKeyName(keyIdentity, True) makeKey = True self.log.debug("Found key: " + defaultKey.toUri() + " renaming as: " + newKeyName.toUri()) keyType = self._identityStorage.getKeyType(defaultKey) keyDer = self._identityStorage.getKey(defaultKey) if makeKey: try: privateDer = self._identityManager.getPrivateKey(defaultKey) except SecurityException: # XXX: is recovery impossible? pass else: try: self._identityStorage.addKey(newKeyName, keyType, keyDer) self._identityManager.addPrivateKey(newKeyName, privateDer) except SecurityException: # TODO: key shouldn't exist... pass message = CertificateRequestMessage() message.command.keyType = keyType message.command.keyBits = keyDer.toRawStr() for component in range(newKeyName.size()): message.command.keyName.components.append( newKeyName.get(component).toEscapedString()) paramComponent = ProtobufTlv.encode(message) interestName = Name(self._policyManager.getTrustRootIdentity()).append( "certificateRequest").append(paramComponent) interest = Interest(interestName) interest.setInterestLifetimeMilliseconds( 10000) # takes a tick to verify and sign self._hmacHandler.signInterest(interest, keyName=self.prefix) self.log.info("Sending certificate request to controller") self.log.debug("Certificate request: " + interest.getName().toUri()) self.face.expressInterest(interest, self._onCertificateReceived, self._onCertificateTimeout)
def _updateCapabilities(self): """ Send the controller a list of our commands. """ fullCommandName = Name(self._policyManager.getTrustRootIdentity() ).append('updateCapabilities') capabilitiesMessage = UpdateCapabilitiesCommandMessage() for command in self._commands: commandName = Name(self.prefix).append(Name(command.suffix)) capability = capabilitiesMessage.capabilities.add() for i in range(commandName.size()): capability.commandPrefix.components.append( str(commandName.get(i).getValue())) for kw in command.keywords: capability.keywords.append(kw) capability.needsSignature = command.isSigned encodedCapabilities = ProtobufTlv.encode(capabilitiesMessage) fullCommandName.append(encodedCapabilities) interest = Interest(fullCommandName) interest.setInterestLifetimeMilliseconds(5000) self.face.makeCommandInterest(interest) signature = self._policyManager._extractSignature(interest) self.log.info("Sending capabilities to controller") self.face.expressInterest(interest, self._onCapabilitiesAck, self._onCapabilitiesTimeout) # update twice a minute self.loop.call_later(30, self._updateCapabilities)
def decode_cmd_param_blob( interest: Interest) -> RepoCommandParameterMessage: """ Decode the command interest and return a RepoCommandParameterMessage object. Command interests have the format of: /<routable_repo_prefix>/insert/<cmd_param_blob>/<timestamp>/<random-value>/<SignatureInfo>/<SignatureValue> Throw RuntimeError on decoding failure. """ parameter = RepoCommandParameterMessage() param_blob = interest.getName()[-5].getValue() try: ProtobufTlv.decode(parameter, param_blob) except RuntimeError as exc: raise exc return parameter
def _sendCertificateRequest(self, keyIdentity): """ We compose a command interest with our public key info so the controller can sign us a certificate that can be used with other nodes in the network. """ try: defaultKey = self._identityStorage.getDefaultKeyNameForIdentity(keyIdentity) except SecurityException: defaultKey = self._identityManager.generateRSAKeyPairAsDefault(keyIdentity) self.log.debug("Key name: " + defaultKey.toUri()) message = CertificateRequestMessage() publicKey = self._identityManager.getPublicKey(defaultKey) message.command.keyType = publicKey.getKeyType() message.command.keyBits = publicKey.getKeyDer().toRawStr() for component in range(defaultKey.size()): message.command.keyName.components.append(defaultKey.get(component).toEscapedString()) paramComponent = ProtobufTlv.encode(message) interestName = Name(self._policyManager.getTrustRootIdentity()).append("certificateRequest").append(paramComponent) interest = Interest(interestName) interest.setInterestLifetimeMilliseconds(10000) # takes a tick to verify and sign self._hmacHandler.signInterest(interest, keyName=self.prefix) self.log.info("Sending certificate request to controller") self.log.debug("Certificate request: "+interest.getName().toUri()) self.face.expressInterest(interest, self._onCertificateReceived, self._onCertificateTimeout)
def make_command(self, module, verb, **kwargs): name = Name('/localhost/nfd').append(module).append(verb) # Command Parameters cmd_param = ControlCommandMessage() if 'name' in kwargs: name_param = kwargs['name'] for compo in name_param: cmd_param.control_parameters.name.component.append(compo.getValue().toBytes()) if 'strategy' in kwargs: name_param = kwargs['strategy'] for compo in name_param: cmd_param.control_parameters.strategy.name.component.append(compo.getValue().toBytes()) for key in ['uri', 'local_uri']: if key in kwargs: setattr(cmd_param.control_parameters, key, kwargs[key].encode('utf-8')) for key in ['face_id', 'origin', 'cost', 'capacity', 'count', 'base_cong_mark', 'def_cong_thres', 'mtu', 'flags', 'mask', 'exp_period']: if key in kwargs: setattr(cmd_param.control_parameters, key, kwargs[key]) param_blob = ProtobufTlv.encode(cmd_param) name.append(Name.Component(param_blob)) # Command Interest Components ret = Interest(name) ret.canBePrefix = True self.face.makeCommandInterest(ret) return ret
def wireDecode(self, input): """ Decode the input and update this ContentMetaInfo. :param input: The array with the bytes to decode. :type input: An array type with int elements """ meta = ContentMetaInfoMessage() ProtobufTlv.decode(meta, input) self.clear() self._contentType = meta.content_meta_info.content_type self._timestamp = float(meta.content_meta_info.timestamp) self._hasSegments = meta.content_meta_info.has_segments if len(meta.content_meta_info.other) > 0: self._other = Blob(bytearray(meta.content_meta_info.other), False)
def onLightingCommand(self, prefix, interest, transport, prefixId): #print datetime.datetime.now() self.receiveFile.write('{0:f}'.format(self.unix_time_now()) + '\n') interestName = Name(interest.getName()) #interstname: /ndn/ucla.edu/sculptures/ai_bus/lights/setRGB/%83%0D%84%0B%87%09%89%01%04%8A%01%01%8B%01%01 #d: <pyndn.data.Data object at 0xb64825d0> print "interstname", interestName.toUri() d = Data(interest.getName()) # get the command parameters from the name try: commandComponent = interest.getName().get(prefix.size()) #print commandComponent.toEscapedString():setRGB #print "prefix ",prefix.toUri():/ndn/ucla.edu/sculpture/ai_bus/lights #print "get name",interest.getName().toUri() commandParams = interest.getName().get(prefix.size()+1) #print "commandParams ",commandParams:%83%0D%84%0B%87%09%89%01%04%8A%01%01%8B%01%01 lightingCommand = LightCommandMessage() ProtobufTlv.decode(lightingCommand, commandParams.getValue()) #self.log.info("Command: " + commandComponent.toEscapedString()) requestedColor = lightingCommand.command.pattern.colors[0] colorStr = str((requestedColor.r, requestedColor.g, requestedColor.b)) #self.log.info("Requested color: " + colorStr) self.setPayloadColor(0, requestedColor) self.lightState = not self.lightState if self.lightState: print "Off" else: print "On" #print requestedColor self.sendLightPayload(1) d.setContent("Gotcha: " + colorStr+ "\n") except KeyboardInterrupt: print "key interrupt" sys.exit(1) except Exception as e: print e d.setContent("Bad command\n") finally: d.getMetaInfo().setFinalBlockID(0) self.signData(d) encodedData = d.wireEncode() transport.send(encodedData.toBuffer())
def requestInsert(face, repoCommandPrefix, fetchName, onInsertStarted, onFailed, startBlockId = None, endBlockId = None): """ Send a command interest for the repo to fetch the given fetchName and insert it in the repo. Since this calls expressInterest, your application must call face.processEvents. :param Face face: The Face used to call makeCommandInterest and expressInterest. :param Name repoCommandPrefix: The repo command prefix. :param Name fetchName: The name to fetch. If startBlockId and endBlockId are supplied, then the repo will request multiple segments by appending the range of block IDs (segment numbers). :param onInsertStarted: When the request insert command successfully returns, this calls onInsertStarted(). :type onInsertStarted: function object :param onFailed: If the command fails for any reason, this prints an error and calls onFailed(). :type onFailed: function object :param int startBlockId: (optional) The starting block ID (segment number) to fetch. :param int endBlockId: (optional) The end block ID (segment number) to fetch. """ # repo_command_parameter_pb2 was produced by protoc. parameter = repo_command_parameter_pb2.RepoCommandParameterMessage() # Add the Name. for i in range(fetchName.size()): parameter.repo_command_parameter.name.component.append( fetchName[i].getValue().toBytes()) # Add startBlockId and endBlockId if supplied. if startBlockId != None: parameter.repo_command_parameter.start_block_id = startBlockId if endBlockId != None: parameter.repo_command_parameter.end_block_id = endBlockId # Create the command interest. interest = Interest(Name(repoCommandPrefix).append("insert") .append(Name.Component(ProtobufTlv.encode(parameter)))) face.makeCommandInterest(interest) # Send the command interest and get the response or timeout. def onData(interest, data): # repo_command_response_pb2 was produced by protoc. response = repo_command_response_pb2.RepoCommandResponseMessage() try: ProtobufTlv.decode(response, data.content) except: dump("Cannot decode the repo command response") onFailed() if response.repo_command_response.status_code == 100: onInsertStarted() else: dump("Got repo command error code", response.repo_command_response.status_code) onFailed() def onTimeout(interest): dump("Insert repo command timeout") onFailed() face.expressInterest(interest, onData, onTimeout)
def processFaceStatus(encodedFaceStatus, prefix, uri, face, enabled): """ This is called when all the segments are received to decode the encodedFaceStatus as a TLV FaceStatus message. If the face ID exists for the face URL, use it to call registerRoute(), otherwise send a /localhost/nfd/faces/create command to create the face. :param Blob encodedFaceStatus: The TLV-encoded FaceStatus. :param Name prefix: The prefix name to register. :param str uri: The remote URI in case we need to tell NFD to create a face. :param Face face: The Face which is used to sign the command interest and call expressInterest. :param enabled: On success or error, set enabled[0] = False. :type enabled: An array with one bool element """ if encodedFaceStatus.size() == 0: # No result, so we need to tell NFD to create the face. # Encode the ControlParameters. message = \ control_parameters_pb2.ControlParametersTypes.ControlParametersMessage() message.control_parameters.uri = uri encodedControlParameters = ProtobufTlv.encode(message) interest = Interest(Name("/localhost/nfd/faces/create")) interest.getName().append(encodedControlParameters) interest.setInterestLifetimeMilliseconds(10000) def onData(localInterest, data): processCreateFaceResponse(data.getContent(), prefix, face, enabled) def onTimeout(localInterest): enabled[0] = False dump("Face create command timed out.") # Sign and express the interest. face.makeCommandInterest(interest) face.expressInterest(interest, onData, onTimeout) else: decodedFaceStatus = face_status_pb2.FaceStatusMessage() ProtobufTlv.decode(decodedFaceStatus, encodedFaceStatus) faceId = decodedFaceStatus.face_status[0].face_id dump("Found face ID ", faceId) registerRoute(prefix, faceId, face, enabled)
def onVerifiedAppRequest(interest): # TODO: for now, we automatically grant access to any valid signed interest print("verified! send response!") message = AppRequestMessage() ProtobufTlv.decode(message, interest.getName().get(prefix.size() + 1).getValue()) certName = Name("/".join(message.command.idName.components)) dataPrefix = Name("/".join(message.command.dataPrefix.components)) appName = message.command.appName isUpdated = self.updateTrustSchema(appName, certName, dataPrefix, True) response = Data(interest.getName()) if isUpdated: response.setContent("{\"status\": 200, \"message\": \"granted, trust schema updated OK\" }") self.log.info("Verified and granted application publish request") else: response.setContent("{\"status\": 400, \"message\": \"not granted, requested publishing namespace already exists\" }") self.log.info("Verified and but requested namespace already exists") self.sendData(response) return
def handleCommandInterests(self, prefix, interest, transport, prefixId): # TODO: verification interestName = interest.getName() if len(interestName) <= len(prefix)+4: self.log.info("Bad command interest") commandName = str(interestName[len(prefix)].getValue()) responseMessage = RepoCommandResponseMessage() if commandName == 'insert': commandParams = interestName[len(prefix)+1].getValue() commandMessage = RepoCommandParameterMessage() ProtobufTlv.decode(commandMessage, commandParams) dataName = Name() fullSchemaName = Name() for component in commandMessage.command.name.components: fullSchemaName.append(component) if component == '_': continue dataName.append(component) self.log.info("Insert request for {}".format(dataName)) responseMessage.response.status_code = 100 processId = self.currentProcessId self.currentProcessId += 1 responseMessage.response.process_id = processId else: responseMessage.response.status_code = 403 responseData = Data(interestName) responseData.setContent(ProtobufTlv.encode(responseMessage)) transport.send(responseData.wireEncode().buf()) # now send the interest out to the publisher # TODO: pendingProcesses becomes list of all processes as objects i = Interest(dataName) i.setChildSelector(1) i.setInterestLifetimeMilliseconds(4000) try: self.pendingProcesses[processId] = (dataName, 100) except NameError: pass # wasn't valid insert request else: self._insertFace.expressInterest(i, self._onInsertionDataReceived, self._onInsertionDataTimeout)
def _sendCertificateRequest(self, keyIdentity): """ We compose a command interest with our public key info so the controller can sign us a certificate that can be used with other nodes in the network. """ #TODO: GENERATE A NEW PUBLIC/PRIVATE PAIR INSTEAD OF COPYING makeKey = False try: defaultKey = self._identityStorage.getDefaultKeyNameForIdentity(keyIdentity) newKeyName = defaultKey except SecurityException: defaultIdentity = self._keyChain.getDefaultIdentity() defaultKey = self._identityStorage.getDefaultKeyNameForIdentity(defaultIdentity) newKeyName = self._identityStorage.getNewKeyName(keyIdentity, True) makeKey = True self.log.debug("Found key: " + defaultKey.toUri()+ " renaming as: " + newKeyName.toUri()) keyType = self._identityStorage.getKeyType(defaultKey) keyDer = self._identityStorage.getKey(defaultKey) if makeKey: try: privateDer = self._identityManager.getPrivateKey(defaultKey) except SecurityException: # XXX: is recovery impossible? pass else: try: self._identityStorage.addKey(newKeyName, keyType, keyDer) self._identityManager.addPublicKey(newKeyName, keyDer) self._identityManager.addPrivateKey(newKeyName, privateDer) except SecurityException: # TODO: key shouldn't exist... pass message = CertificateRequestMessage() message.command.keyType = keyType message.command.keyBits = keyDer.toRawStr() for component in range(newKeyName.size()): message.command.keyName.components.append(newKeyName.get(component).toEscapedString()) paramComponent = ProtobufTlv.encode(message) interestName = Name(self._policyManager.getTrustRootIdentity()).append("certificateRequest").append(paramComponent) interest = Interest(interestName) interest.setInterestLifetimeMilliseconds(10000) # takes a tick to verify and sign self._hmacHandler.signInterest(interest, keyName=self.prefix) self.log.info("Sending certificate request to controller") self.log.debug("Certificate request: "+interest.getName().toUri()) self.face.expressInterest(interest, self._onCertificateReceived, self._onCertificateTimeout)
def createCheckInterest(self, fullName, checkNum): insertionName = Name(self.repoPrefix).append('insert check') commandParams = RepoCommandParameterMessage() interestName = Name(fullName) commandParams.repo_command_parameter.process_id = checkNum for i in range(interestName.size()): commandParams.repo_command_parameter.name.component.append(str(interestName.get(i).getValue())) commandName = insertionName.append(ProtobufTlv.encode(commandParams)) interest = Interest(commandName) return interest
def createCheckInterest(fullName, checkNum): insertionName = Name("/repotest/repo/insert check") commandParams = RepoCommandParameterMessage() interestName = Name(fullName) commandParams.repo_command_parameter.process_id = checkNum for i in range(interestName.size()): commandParams.repo_command_parameter.name.component.append(interestName.get(i).toEscapedString()) commandName = insertionName.append(ProtobufTlv.encode(commandParams)) interest = Interest(commandName) return interest
def _updateDeviceCapabilities(self, interest): """ Take the received capabilities update interest and update our directory listings. """ # we assume the sender is the one who signed the interest... signature = self._policyManager._extractSignature(interest) certificateName = signature.getKeyLocator().getKeyName() senderIdentity = IdentityCertificate.certificateNameToPublicKeyName(certificateName).getPrefix(-1) self.log.info('Updating capabilities for {}'.format(senderIdentity.toUri())) # get the params from the interest name messageComponent = interest.getName().get(self.prefix.size()+1) message = UpdateCapabilitiesCommandMessage() ProtobufTlv.decode(message, messageComponent.getValue()) # we remove all the old capabilities for the sender tempDirectory = defaultdict(list) for keyword in self._directory: tempDirectory[keyword] = [cap for cap in self._directory[keyword] if not senderIdentity.match(Name(cap['name']))] # then we add the ones from the message for capability in message.capabilities: capabilityPrefix = Name() for component in capability.commandPrefix.components: capabilityPrefix.append(component) commandUri = capabilityPrefix.toUri() if not senderIdentity.match(capabilityPrefix): self.log.error("Node {} tried to register another prefix: {} - ignoring update".format( senderIdentity.toUri(),commandUri)) else: for keyword in capability.keywords: allUris = [info['name'] for info in tempDirectory[keyword]] if capabilityPrefix not in allUris: listing = {'signed':capability.needsSignature, 'name':commandUri} tempDirectory[keyword].append(listing) self._directory= tempDirectory
def _handleCertificateRequest(self, interest, transport): """ Extracts a public key name and key bits from a command interest name component. Generates a certificate if the request is verifiable. This expects an HMAC signed interest. """ message = CertificateRequestMessage() commandParamsTlv = interest.getName().get(self.prefix.size()+1) ProtobufTlv.decode(message, commandParamsTlv.getValue()) signature = HmacHelper.extractInterestSignature(interest) deviceSerial = str(signature.getKeyLocator().getKeyName().get(-1).getValue()) response = Data(interest.getName()) certData = None hmac = None try: hmac = self._hmacDevices[deviceSerial] if hmac.verifyInterest(interest): certData = self._createCertificateFromRequest(message) # remove this hmac; another request will require a new pin self._hmacDevices.pop(deviceSerial) except KeyError: self.log.warn('Received certificate request for device with no registered key') except SecurityException: self.log.warn('Could not create device certificate') else: self.log.info('Creating certificate for device {}'.format(deviceSerial)) if certData is not None: response.setContent(certData.wireEncode()) response.getMetaInfo().setFreshnessPeriod(10000) # should be good even longer else: response.setContent("Denied") if hmac is not None: hmac.signData(response) self.sendData(response, transport, False)
def initiateContentStoreInsertion(self, repoCommandPrefix, data): fetchName = data.getName() parameter = repo_command_parameter_pb2.RepoCommandParameterMessage() # Add the Name. for i in range(fetchName.size()): parameter.repo_command_parameter.name.component.append( fetchName[i].getValue().toBytes()) # Create the command interest. interest = Interest(Name(repoCommandPrefix).append("insert") .append(Name.Component(ProtobufTlv.encode(parameter)))) self.face.makeCommandInterest(interest) self.face.expressInterest(interest, self.onRepoData, self.onRepoTimeout)
def createCommandInterest(prefix="/testlight/setRGB", color=(255,0,128)): interestName = Name(prefix) commandParams = LightCommandMessage() messageColor = commandParams.command.pattern.colors.add() messageColor.r = color[0] messageColor.g = color[1] messageColor.b = color[2] commandName = interestName.append(ProtobufTlv.encode(commandParams)) interest = Interest(commandName) interest.setInterestLifetimeMilliseconds(2000) return interest