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 _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)
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)
async def _check(self, method: str, repo_name: str, process_id: int) -> RepoCommandResponseMessage: """ Return parsed insert check response message. """ parameter = RepoCommandParameterMessage() parameter.repo_command_parameter.process_id = process_id param_blob = ProtobufTlv.encode(parameter) name = Name(repo_name).append(method + ' check').append(Name.Component(param_blob)) interest = Interest(name) interest.canBePrefix = True interest.setInterestLifetimeMilliseconds(1000) self.face.makeCommandInterest(interest) logging.info('Send ' + method + 'check interest') ret = await fetch_data_packet(self.face, interest) if not isinstance(ret, Data): logging.warning('Check error') return None try: response = self.decode_cmd_response_blob(ret) except RuntimeError as exc: logging.warning('Response blob decoding failed') return None return response
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 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 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 _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)
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
def main(): face = Face() keychain = KeyChain() face.setCommandSigningInfo(keychain, keychain.getDefaultCertificateName()) running = True # The following line doesn't work sometimes # interest = Interest("/icear-server/calc") interest = Interest(Name("/icear-server/calc")) param_msg = SegmentParameterMessage() param_msg.segment_parameter.name.component.append( bytes("example-data", "utf-8")) param_msg.segment_parameter.start_frame = 2 param_msg.segment_parameter.end_frame = 3 op = param_msg.segment_parameter.operations.components.add() op.model = bytes("deeplab", "utf-8") op.flags = 0 op = param_msg.segment_parameter.operations.components.add() op.model = bytes("la_muse", "utf-8") op.flags = 0 interest.name.append(ProtobufTlv.encode(param_msg)) interest.mustBeFresh = True interest.interestLifetimeMilliseconds = 4000.0 interest.setCanBePrefix(True) def on_data(_, data): # type: (Interest, Data) -> None nonlocal running print(data.name.toUri()) print(data.content.toBytes()) running = False def on_timeout(_): nonlocal running print("Timeout") running = False def on_nack(_, nack): # type: (Interest, NetworkNack) -> None nonlocal running print("NACK") print(nack.getReason()) running = False face.expressInterest(interest, on_data, on_timeout, on_nack) while running: face.processEvents() time.sleep(0.01) face.shutdown()
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 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 createLightingCommand(self, color): interestName = Name(self.lightPrefix).append('setRGB') print "interest prefix", self.lightPrefix, type(self.lightPrefix) 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) return interest
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 reply_to_cmd(self, interest: Interest, response: RepoCommandResponseMessage): """ Reply to a command interest """ logging.info('Reply to command: {}'.format(interest.getName())) response_blob = ProtobufTlv.encode(response) data = Data(interest.getName()) data.metaInfo.freshnessPeriod = 1000 data.setContent(response_blob) self.keychain.sign(data) self.face.putData(data)
def stopRepoWatch(face, repoCommandPrefix, watchPrefix, onRepoWatchStopped, onFailed): """ Send a command interest for the repo to stop watching the given watchPrefix. 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 watchPrefix: The prefix that the repo will stop watching. :param onRepoWatchStopped: When the stop watch command successfully returns, this calls onRepoWatchStopped(). :type onRepoWatchStopped: function object :param onFailed: If the command fails for any reason, this prints an error and calls onFailed(). :type onFailed: function object """ # repo_command_parameter_pb2 was produced by protoc. parameter = repo_command_parameter_pb2.RepoCommandParameterMessage() for i in range(watchPrefix.size()): parameter.repo_command_parameter.name.component.append( watchPrefix[i].getValue().toBytes()) # Create the command interest. interest = Interest( Name(repoCommandPrefix).append("watch").append("stop").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 == 101: onRepoWatchStopped() else: dump("Got repo command error code", response.repo_command_response.status_code) onFailed() def onTimeout(interest): dump("Stop repo watch command timeout") onFailed() face.expressInterest(interest, onData, onTimeout)
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
def sendRepoInsertCommand(self, dataName): self.log.debug('Sending insert command for {}'.format(dataName)) commandMessage = RepoCommandParameterMessage() command = commandMessage.command for component in dataName: command.name.components.append(str(component.getValue())) command.start_block_id = command.end_block_id = 0 commandComponent = ProtobufTlv.encode(commandMessage) interestName = Name(self.repoPrefix).append('insert') interestName.append(commandComponent) interest = Interest(interestName) interest.setInterestLifetimeMilliseconds(4000) self.face.makeCommandInterest(interest) self.face.expressInterest(interest, self.onDataReceived, self.onTimeout)
def stopRepoWatch(face, repoCommandPrefix, watchPrefix, onRepoWatchStopped, onFailed): """ Send a command interest for the repo to stop watching the given watchPrefix. 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 watchPrefix: The prefix that the repo will stop watching. :param onRepoWatchStopped: When the stop watch command successfully returns, this calls onRepoWatchStopped(). :type onRepoWatchStopped: function object :param onFailed: If the command fails for any reason, this prints an error and calls onFailed(). :type onFailed: function object """ # repo_command_parameter_pb2 was produced by protoc. parameter = repo_command_parameter_pb2.RepoCommandParameterMessage() for i in range(watchPrefix.size()): parameter.repo_command_parameter.name.component.append( watchPrefix[i].getValue().toBytes()) # Create the command interest. interest = Interest(Name(repoCommandPrefix).append("watch").append("stop") .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 == 101: onRepoWatchStopped() else: dump("Got repo command error code", response.repo_command_response.status_code) onFailed() def onTimeout(interest): dump("Stop repo watch 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 _addDeviceToNetwork(self, serial, suffix, pin): self.ui.alert("Sending pairing info to gateway...", False) # we must encrypt this so no one can see the pin! message = DevicePairingInfoMessage() message.info.deviceSuffix = suffix message.info.deviceSerial = serial message.info.devicePin = pin rawBytes = ProtobufTlv.encode(message) encryptedBytes = self._identityManager.encryptForIdentity(rawBytes, self.prefix) encodedBytes = base64.urlsafe_b64encode(str(encryptedBytes)) interestName = Name(self.prefix).append("addDevice").append(encodedBytes) interest = Interest(interestName) # todo: have the controller register this console as a listener # and update it with pairing status interest.setInterestLifetimeMilliseconds(5000) self.face.makeCommandInterest(interest) self.face.expressInterest(interest, self._onAddDeviceResponse, self._onAddDeviceTimeout)
def createInsertInterest(fullName): # we have to do the versioning when we poke the repo interestName = Name(fullName) logger.debug('Creating insert interest for: '+interestName.toUri()) insertionName = Name("/repotest/repo/insert") commandParams = RepoCommandParameterMessage() for i in range(interestName.size()): commandParams.repo_command_parameter.name.component.append(interestName.get(i).toEscapedString()) commandParams.repo_command_parameter.start_block_id = 0 commandParams.repo_command_parameter.end_block_id = 0 commandName = insertionName.append(ProtobufTlv.encode(commandParams)) interest = Interest(commandName) return interest
def main(): # Silence the warning from Interest wire encode. Interest.setDefaultCanBePrefix(True) prefix = Name("/nfd/edu/ucla/remap/test") # Route to aleph.ndn.ucla.edu. Have to use the canonical name with an IP # address and port. uri = "udp4://128.97.98.7:6363" # The default Face connects to the local NFD. face = Face() # Use the system default key chain and certificate name to sign commands. keyChain = KeyChain() face.setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName()) # Create the /localhost/nfd/faces/query command interest, including the # FaceQueryFilter. Construct the FaceQueryFilter using the structure in # face_query_filter_pb2 which was produced by protoc. message = face_query_filter_pb2.FaceQueryFilterMessage() filter = message.face_query_filter.add() filter.uri = uri encodedFilter = ProtobufTlv.encode(message) interest = Interest(Name("/localhost/nfd/faces/query")) interest.getName().append(encodedFilter) enabled = [True] def onComplete(content): processFaceStatus(content, prefix, uri, face, enabled) def onError(errorCode, message): enabled[0] = False dump(message) SegmentFetcher.fetch(face, interest, None, onComplete, onError) # Loop calling processEvents until a callback sets enabled[0] = False. while enabled[0]: face.processEvents() # We need to sleep for a few milliseconds so we don't use 100% of the CPU. time.sleep(0.01)
def registerRoute(prefix, faceId, face, enabled): """ Use /localhost/nfd/rib/register to register the prefix to the faceId. :param Name prefix: The prefix name to register. :param int faceId: The face ID. :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 """ # Use default values origin = 255 cost = 0 CHILD_INHERIT = 1 flags = CHILD_INHERIT message = control_parameters_pb2.ControlParametersTypes.ControlParametersMessage( ) for i in range(prefix.size()): message.control_parameters.name.component.append( prefix[i].getValue().toBytes()) message.control_parameters.face_id = faceId message.control_parameters.origin = origin message.control_parameters.cost = cost message.control_parameters.flags = flags encodedControlParameters = ProtobufTlv.encode(message) interest = Interest(Name("/localhost/nfd/rib/register")) interest.getName().append(encodedControlParameters) interest.setInterestLifetimeMilliseconds(10000) # Sign and express the interest. face.makeCommandInterest(interest) def onData(localInterest, data): enabled[0] = False processRegisterResponse(data.getContent()) def onTimeout(localInterest): enabled[0] = False dump("Register route command timed out.") face.expressInterest(interest, onData, onTimeout)
def wireEncode(self): """ Encode this ContentMetaInfo. :return: The encoding Blob. :rtype: Blob """ if self._timestamp == None: raise RuntimeError( "The ContentMetaInfo timestamp is not specified") meta = ContentMetaInfoMessage() meta.content_meta_info.content_type = self._contentType meta.content_meta_info.timestamp = int(round(self._timestamp)) meta.content_meta_info.has_segments = self._hasSegments if not self._other.isNull() and self._other.size() > 0: meta.content_meta_info.other = self._other.toBytes() return ProtobufTlv.encode(meta)
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 main(): prefix = Name("/nfd/edu/ucla/remap/test") # Route to aleph.ndn.ucla.edu. Have to use the canonical name with an IP # address and port. uri = "udp4://128.97.98.7:6363" # The default Face connects to the local NFD. face = Face() # Use the system default key chain and certificate name to sign commands. keyChain = KeyChain() face.setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName()) # Create the /localhost/nfd/faces/query command interest, including the # FaceQueryFilter. Construct the FaceQueryFilter using the structure in # face_query_filter_pb2 which was produced by protoc. message = face_query_filter_pb2.FaceQueryFilterMessage() filter = message.face_query_filter.add() filter.uri = uri encodedFilter = ProtobufTlv.encode(message) interest = Interest(Name("/localhost/nfd/faces/query")) interest.getName().append(encodedFilter) enabled = [True] def onComplete(content): processFaceStatus(content, prefix, uri, face, enabled) def onError(errorCode, message): enabled[0] = False dump(message) SegmentFetcher.fetch( face, interest, SegmentFetcher.DontVerifySegment, onComplete, onError) # Loop calling processEvents until a callback sets enabled[0] = False. while enabled[0]: face.processEvents() # We need to sleep for a few milliseconds so we don't use 100% of the CPU. time.sleep(0.01)
async def query_face_id(self, uri): query_filter = FaceQueryFilterMessage() query_filter.face_query_filter.uri = uri.encode('utf-8') query_filter_msg = ProtobufTlv.encode(query_filter) name = Name("/localhost/nfd/faces/query").append(Name.Component(query_filter_msg)) interest = Interest(name) interest.mustBeFresh = True interest.canBePrefix = True ret = await fetch_data_packet(self.face, interest) if not isinstance(ret, Data): return None msg = FaceStatusMessage() try: ProtobufTlv.decode(msg, ret.content) except RuntimeError as exc: logging.fatal("Decoding Error %s", exc) return None if len(msg.face_status) <= 0: return None return msg.face_status[0].face_id
def registerRoute(prefix, faceId, face, enabled): """ Use /localhost/nfd/rib/register to register the prefix to the faceId. :param Name prefix: The prefix name to register. :param int faceId: The face ID. :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 """ # Use default values origin = 255 cost = 0 CHILD_INHERIT = 1 flags = CHILD_INHERIT message = control_parameters_pb2.ControlParametersTypes.ControlParametersMessage() for i in range(prefix.size()): message.control_parameters.name.component.append(prefix[i].getValue().toBytes()) message.control_parameters.face_id = faceId message.control_parameters.origin = origin message.control_parameters.cost = cost message.control_parameters.flags = flags encodedControlParameters = ProtobufTlv.encode(message) interest = Interest(Name("/localhost/nfd/rib/register")) interest.getName().append(encodedControlParameters) interest.setInterestLifetimeMilliseconds(10000) # Sign and express the interest. face.makeCommandInterest(interest) def onData(localInterest, data): enabled[0] = False processRegisterResponse(data.getContent()) def onTimeout(localInterest): enabled[0] = False dump("Register route command timed out.") face.expressInterest(interest, onData, onTimeout)
def _addDeviceToNetwork(self, serial, suffix, pin): self.ui.alert('Sending pairing info to gateway...', False) # we must encrypt this so no one can see the pin! message = DevicePairingInfoMessage() message.info.deviceSuffix = suffix message.info.deviceSerial = serial message.info.devicePin = pin rawBytes = ProtobufTlv.encode(message) encryptedBytes = self._identityManager.encryptForIdentity( rawBytes, self.prefix) encodedBytes = base64.urlsafe_b64encode(str(encryptedBytes)) interestName = Name( self.prefix).append('addDevice').append(encodedBytes) interest = Interest(interestName) # todo: have the controller register this console as a listener # and update it with pairing status interest.setInterestLifetimeMilliseconds(5000) self.face.makeCommandInterest(interest) self.face.expressInterest(interest, self._onAddDeviceResponse, self._onAddDeviceTimeout)
def _addDeviceToNetwork(self, deviceSerial, newDeviceSuffix, pin): h = HmacHelper(pin) self._hmacDevices[deviceSerial] = h d = DeviceConfigurationMessage() for source, dest in [(self.networkPrefix, d.configuration.networkPrefix), (self.deviceSuffix, d.configuration.controllerName), (newDeviceSuffix, d.configuration.deviceSuffix)]: for i in range(source.size()): component = source.get(i) dest.components.append(component.getValue().toRawStr()) interestName = Name('/localhop/configure').append(Name(deviceSerial)) encodedParams = ProtobufTlv.encode(d) interestName.append(encodedParams) interest = Interest(interestName) h.signInterest(interest) self.face.expressInterest(interest, self._deviceAdditionResponse, self._deviceAdditionTimedOut)
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 = fetch prefix. for compo in fetchName: parameter.repo_command_parameter.name.component.append( compo.getValue().toBytes()) # Create the command interest. interest = Interest( Name(repoCommandPrefix).append("cancel").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 == 101: onInsertStarted() else: dump("Got repo command error code", response.repo_command_response.status_code) onFailed() def onTimeout(interest): dump("Cancel repo command timeout") onFailed() face.expressInterest(interest, onData, onTimeout)
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 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. """ 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) face.expressInterest(interest, onRepoData, onRepoTimeout)
def nodata_reply(self, name, code, retry_after=0.0): # type: (Name, int, float) -> None logging.info("Reply with code: %s", code) data = Data(name) metainfo = MetaInfo() msg = ServerResponseMessage() msg.server_response.ret_code = code if code != RET_OK: metainfo.type = ContentType.NACK else: metainfo.type = ContentType.BLOB if retry_after > 0.1: metainfo.freshnessPeriod = int(retry_after / 10) msg.server_response.retry_after = int(retry_after) else: metainfo.freshnessPeriod = 600 data.setMetaInfo(metainfo) data.setContent(ProtobufTlv.encode(msg)) self.keychain.sign(data) self.face.putData(data)
def sendAppRequest(self, certificateName, dataPrefix, applicationName, onRequestSuccess, onRequestFailed): message = AppRequestMessage() for component in range(certificateName.size()): message.command.idName.components.append(certificateName.get(component).toEscapedString()) for component in range(dataPrefix.size()): message.command.dataPrefix.components.append(dataPrefix.get(component).toEscapedString()) message.command.appName = applicationName paramComponent = ProtobufTlv.encode(message) requestInterest = Interest(Name(self._controllerName).append("requests").append(paramComponent)) requestInterest.setInterestLifetimeMilliseconds(4000) self._face.makeCommandInterest(requestInterest) appRequestTimeoutCnt = 3 self._face.expressInterest(requestInterest, lambda interest, data : self.onAppRequestData(interest, data, onRequestSuccess, onRequestFailed), lambda interest : self.onAppRequestTimeout(interest, onRequestSuccess, onRequestFailed, appRequestTimeoutCnt)) print "Application publish request sent: " + requestInterest.getName().toUri() return
def _addDeviceToNetwork(self, deviceSerial, newDeviceSuffix, pin): h = HmacHelper(pin) self._hmacDevices[deviceSerial] = h d = DeviceConfigurationMessage() for source, dest in [ (self.networkPrefix, d.configuration.networkPrefix), (self.deviceSuffix, d.configuration.controllerName), (newDeviceSuffix, d.configuration.deviceSuffix) ]: for i in range(source.size()): component = source.get(i) dest.components.append(component.getValue().toRawStr()) interestName = Name('/home/configure').append(Name(deviceSerial)) encodedParams = ProtobufTlv.encode(d) interestName.append(encodedParams) interest = Interest(interestName) h.signInterest(interest) self.face.expressInterest(interest, self._deviceAdditionResponse, self._deviceAdditionTimedOut)
def createInsertInterest(self, fullName): ''' For poking the repo ''' # we have to do the versioning before we poke the repo interestName = Name(fullName) logger.debug('Creating insert interest for: '+interestName.toUri()) insertionName = Name(self.repoPrefix).append('insert') commandParams = RepoCommandParameterMessage() for i in range(interestName.size()): commandParams.repo_command_parameter.name.component.append(interestName.get(i).getValue().toRawStr()) commandParams.repo_command_parameter.start_block_id = 0 commandParams.repo_command_parameter.end_block_id = 0 commandName = insertionName.append(ProtobufTlv.encode(commandParams)) interest = Interest(commandName) interest.setInterestLifetimeMilliseconds(2000) return interest
def startRepoInsertion(self, data): # For now we only insert raw data into repo parameter = repo_command_parameter_pb2.RepoCommandParameterMessage() # Add the Name. for i in range(data.getName().size()): parameter.repo_command_parameter.name.component.append( data.getName().get(i).toEscapedString()) # Create the command interest. commandInterest = Interest( Name(repoCommandPrefix).append("insert").append( Name.Component(ProtobufTlv.encode(parameter)))) self._face.makeCommandInterest(commandInterest) # Send the command interest and get the response or timeout. 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 onRepoCommandTimeout(interest): if __debug__: print("Insert repo command timeout") self._face.expressInterest(commandInterest, onRepoCommandResponse, onRepoCommandTimeout)
def publish(self, line): # Pull out and parse datetime for log entry # (note we shoudld use point time for timestamp) try: if not ": (point" in line: return point = parse.search("(point {})", line)[0].split(" ") except Exception as detail: print("publish: Parse error for", line, "-", detail) return try: tempTime = datetime.strptime( parse.search("[{}]", line)[0], "%Y-%m-%d %H:%M:%S.%f") except Exception as detail: print("publish: Date/time conversion error for", line, "-", detail) return sensorName = point[0] aggregationNamePrefix = self.pointNameToNDNName(sensorName) dataDict = self.pointToJSON(point) self._lastDataTimestamp = time.time() if aggregationNamePrefix is not None: #if __debug__: # print(dateTime, aggregationNamePrefix, dataDict["timestamp"], "payload:", dataDict["value"]) try: # TODO: since the leaf sensor publisher is not a separate node for now, we also publish aggregated data # of the same sensor over the past given time period in this code; # bms_node code has adaptation for leaf sensor publishers as well, ref: example-sensor1.conf # Here we make the assumption of fixed time window for *all* sensors # First publish aggregation dataTime = int(float(dataDict["timestamp"]) * 1000) if self._startTime == 0: self._startTime = dataTime if not (sensorName in self._dataQueue): # We don't have record of this sensor, so we create an identity for it, and print the cert string for now to get signed sensorIdentityName = Name(self._namespace).append( aggregationNamePrefix).getPrefix(-3) sensorCertificateName = self._keyChain.createIdentityAndCertificate( sensorIdentityName) if __debug__: print("Sensor identity name: " + sensorIdentityName.toUri()) certificateData = self._keyChain.getIdentityManager( )._identityStorage.getCertificate(sensorCertificateName, True) # We should only ask for cert to be signed upon the first run of a certain sensor if DO_CERT_SETUP: if (KeyLocator.getFromSignature( certificateData.getSignature()).getKeyName(). equals(sensorCertificateName.getPrefix(-1))): # Need to configure for remote gateway deployment; for now, remote uses its own branch with my public IP. print("certificate " + sensorCertificateName.toUri() + " asking for signature") response = urllib2.urlopen( "http://192.168.56.1:5000/bms-cert-hack?cert=" + b64encode( certificateData.wireEncode().toBuffer()) + "&cert_prefix=" + sensorIdentityName.toUri() + '&subject_name=' + sensorIdentityName.toUri()).read() signedCertData = Data() signedCertData.wireDecode(Blob( b64decode(response))) self._cache.add(signedCertData) cmdline = ['ndnsec-install-cert', '-'] p = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE) cert, err = p.communicate(response) if p.returncode != 0: raise RuntimeError("ndnsec-install-cert error") else: self._cache.add(certificateData) else: self._cache.add(certificateData) self._dataQueue[sensorName] = DataQueueItem( [], self._startTime + self._defaultInterval, sensorIdentityName, sensorCertificateName) self._dataQueue[sensorName]._dataList.append( dataDict["value"]) elif dataTime > self._dataQueue[sensorName]._timeThreshold: # calculate the aggregation with what's already in the queue, publish data packet, and delete current queue # TODO: This should be mutex locked against self if len(self._dataQueue[sensorName]._dataList) > 0: avg = 0.0 for item in self._dataQueue[sensorName]._dataList: avg += float(item) avg = avg / len(self._dataQueue[sensorName]._dataList) data = Data( Name(self._namespace). append(aggregationNamePrefix).append("avg").append( str(self._dataQueue[sensorName]._timeThreshold) ).append( str(self._dataQueue[sensorName]._timeThreshold + self._defaultInterval))) data.setContent(str(avg)) data.getMetaInfo().setFreshnessPeriod( self.DEFAULT_DATA_LIFETIME) self._keyChain.sign( data, self._dataQueue[sensorName]._certificateName) self._cache.add(data) print("Aggregation produced " + data.getName().toUri()) self._dataQueue[sensorName]._dataList = [dataDict["value"]] self._dataQueue[ sensorName]._timeThreshold = self._dataQueue[ sensorName]._timeThreshold + self._defaultInterval else: self._dataQueue[sensorName]._dataList.append( dataDict["value"]) # Then publish raw data # Timestamp in data name uses the timestamp from data payload instDataPrefix = self.pointNameToNDNName(sensorName, False) dataTemp = self.createData( instDataPrefix, dataDict["timestamp"], json.dumps(dataDict), self._dataQueue[sensorName]._certificateName) if __debug__: print("Produced raw data name " + dataTemp.getName().toUri()) print("Produced raw data content " + dataTemp.getContent().toRawStr()) self._cache.add(dataTemp) # For now we only insert raw data into repo parameter = repo_command_parameter_pb2.RepoCommandParameterMessage( ) # Add the Name. for i in range(dataTemp.getName().size()): parameter.repo_command_parameter.name.component.append( dataTemp.getName().get(i).toEscapedString()) # Create the command interest. commandInterest = Interest( Name(repoCommandPrefix).append("insert").append( Name.Component(ProtobufTlv.encode(parameter)))) self._face.makeCommandInterest(commandInterest) # Send the command interest and get the response or timeout. 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 onRepoCommandTimeout(interest): if __debug__: print("Insert repo command timeout") self._face.expressInterest(commandInterest, onRepoCommandResponse, onRepoCommandTimeout) except Exception as detail: print("publish: Error calling createData for", line, "-", detail)
def publish(self, line): # Pull out and parse datetime for log entry # (note we shoudld use point time for timestamp) try: if not ": (point" in line: return point = parse.search("(point {})", line)[0].split(" ") except Exception as detail: print("publish: Parse error for", line, "-", detail) return try: tempTime = datetime.strptime(parse.search("[{}]", line)[0], "%Y-%m-%d %H:%M:%S.%f") except Exception as detail: print("publish: Date/time conversion error for", line, "-", detail) return sensorName = point[0] aggregationNamePrefix = self.pointNameToNDNName(sensorName) dataDict = self.pointToJSON(point) self._lastDataTimestamp = time.time() if aggregationNamePrefix is not None: #if __debug__: # print(dateTime, aggregationNamePrefix, dataDict["timestamp"], "payload:", dataDict["value"]) try: # TODO: since the leaf sensor publisher is not a separate node for now, we also publish aggregated data # of the same sensor over the past given time period in this code; # bms_node code has adaptation for leaf sensor publishers as well, ref: example-sensor1.conf # Here we make the assumption of fixed time window for *all* sensors # First publish aggregation dataTime = int(float(dataDict["timestamp"]) * 1000) if self._startTime == 0: self._startTime = dataTime if not (sensorName in self._dataQueue): # We don't have record of this sensor, so we create an identity for it, and print the cert string for now to get signed sensorIdentityName = Name(self._namespace).append(aggregationNamePrefix).getPrefix(-3) sensorCertificateName = self._keyChain.createIdentityAndCertificate(sensorIdentityName) if __debug__: print("Sensor identity name: " + sensorIdentityName.toUri()) certificateData = self._keyChain.getIdentityManager()._identityStorage.getCertificate(sensorCertificateName, True) # We should only ask for cert to be signed upon the first run of a certain sensor if DO_CERT_SETUP: if (KeyLocator.getFromSignature(certificateData.getSignature()).getKeyName().equals(sensorCertificateName.getPrefix(-1))): # Need to configure for remote gateway deployment; for now, remote uses its own branch with my public IP. print("certificate " + sensorCertificateName.toUri() + " asking for signature") response = urllib2.urlopen("http://192.168.56.1:5000/bms-cert-hack?cert=" + b64encode(certificateData.wireEncode().toBuffer()) + "&cert_prefix=" + sensorIdentityName.toUri() + '&subject_name=' + sensorIdentityName.toUri()).read() signedCertData = Data() signedCertData.wireDecode(Blob(b64decode(response))) self._cache.add(signedCertData) cmdline = ['ndnsec-install-cert', '-'] p = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE) cert, err = p.communicate(response) if p.returncode != 0: raise RuntimeError("ndnsec-install-cert error") else: self._cache.add(certificateData) else: self._cache.add(certificateData) self._dataQueue[sensorName] = DataQueueItem([], self._startTime + self._defaultInterval, sensorIdentityName, sensorCertificateName) self._dataQueue[sensorName]._dataList.append(dataDict["value"]) elif dataTime > self._dataQueue[sensorName]._timeThreshold: # calculate the aggregation with what's already in the queue, publish data packet, and delete current queue # TODO: This should be mutex locked against self if len(self._dataQueue[sensorName]._dataList) > 0: avg = 0.0 for item in self._dataQueue[sensorName]._dataList: avg += float(item) avg = avg / len(self._dataQueue[sensorName]._dataList) data = Data(Name(self._namespace).append(aggregationNamePrefix).append("avg").append(str(self._dataQueue[sensorName]._timeThreshold)).append(str(self._dataQueue[sensorName]._timeThreshold + self._defaultInterval))) data.setContent(str(avg)) data.getMetaInfo().setFreshnessPeriod(self.DEFAULT_DATA_LIFETIME) self._keyChain.sign(data, self._dataQueue[sensorName]._certificateName) self._cache.add(data) print("Aggregation produced " + data.getName().toUri()) self._dataQueue[sensorName]._dataList = [dataDict["value"]] self._dataQueue[sensorName]._timeThreshold = self._dataQueue[sensorName]._timeThreshold + self._defaultInterval else: self._dataQueue[sensorName]._dataList.append(dataDict["value"]) # Then publish raw data # Timestamp in data name uses the timestamp from data payload instDataPrefix = self.pointNameToNDNName(sensorName, False) dataTemp = self.createData(instDataPrefix, dataDict["timestamp"], json.dumps(dataDict), self._dataQueue[sensorName]._certificateName) if __debug__: print("Produced raw data name " + dataTemp.getName().toUri()) print("Produced raw data content " + dataTemp.getContent().toRawStr()) self._cache.add(dataTemp) # For now we only insert raw data into repo parameter = repo_command_parameter_pb2.RepoCommandParameterMessage() # Add the Name. for i in range(dataTemp.getName().size()): parameter.repo_command_parameter.name.component.append( dataTemp.getName().get(i).toEscapedString()) # Create the command interest. commandInterest = Interest(Name(repoCommandPrefix).append("insert") .append(Name.Component(ProtobufTlv.encode(parameter)))) self._face.makeCommandInterest(commandInterest) # Send the command interest and get the response or timeout. 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 onRepoCommandTimeout(interest): if __debug__: print("Insert repo command timeout") self._face.expressInterest(commandInterest, onRepoCommandResponse, onRepoCommandTimeout) except Exception as detail: print("publish: Error calling createData for", line, "-", detail)