def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) # Now process as Interest or Data. if interest != None: # Call all interest filter callbacks which match. for i in range(len(self._interestFilterTable)): entry = self._interestFilterTable[i] if entry.getFilter().doesMatch(interest.getName()): includeFilter = True # Use getcallargs to test if onInterest accepts 5 args. try: inspect.getcallargs(entry.getOnInterest(), None, None, None, None, None) except TypeError: # Assume onInterest is old-style with 4 arguments. includeFilter = False if includeFilter: try: entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId(), entry.getFilter()) except: logging.exception("Error in onInterest") else: # Old-style onInterest without the filter argument. We # still pass a Face instead of Transport since Face also # has a send method. try: entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId()) except: logging.exception("Error in onInterest") elif data != None: pendingInterests = self._extractEntriesForExpressedInterest( data.getName()) for pendingInterest in pendingInterests: try: pendingInterest.getOnData()(pendingInterest.getInterest(), data) except: logging.exception("Error in onData")
def addMember(self, scheduleName, keyName, key): """ Add a new member with the given key named keyName into a schedule named scheduleName. The member's identity name is keyName.getPrefix(-1). :param str scheduleName: The schedule name. :param Name keyName: The name of the key. :param Blob key: A Blob of the public key DER. :raises GroupManagerDb.Error: If there's no schedule named scheduleName, if the member's identity name already exists, or other database error. """ scheduleId = self._getScheduleId(scheduleName) if scheduleId == -1: raise GroupManagerDb.Error("The schedule does not exist") # Needs to be changed in the future. memberName = keyName.getPrefix(-1) try: cursor = self._database.cursor() cursor.execute( "INSERT INTO members(schedule_id, member_name, key_name, pubkey) " + "values (?, ?, ?, ?)", (scheduleId, sqlite3.Binary(bytearray(memberName.wireEncode(TlvWireFormat.get()).buf())), sqlite3.Binary(bytearray(keyName.wireEncode(TlvWireFormat.get()).buf())), sqlite3.Binary(bytearray(key.buf())))) self._database.commit() cursor.close() except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.addMember: SQLite error: " + str(ex))
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ lpPacket = None if element[0] == Tlv.LpPacket_LpPacket: # Decode the LpPacket and replace element with the fragment. lpPacket = LpPacket() # Set copy False so that the fragment is a slice which will be # copied below. The header fields are all integers and don't need to # be copied. TlvWireFormat.get().decodeLpPacket(lpPacket, element, False) element = lpPacket.getFragmentWireEncoding().buf() # First, decode as Interest or Data. data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: data.setLpPacket(lpPacket) # Now process as Interest or Data. if data != None: if self._onBtleData: self._onBtleData(data)
def addMember(self, scheduleName, keyName, key): """ Add a new member with the given key named keyName into a schedule named scheduleName. The member's identity name is keyName.getPrefix(-1). :param str scheduleName: The schedule name. :param Name keyName: The name of the key. :param Blob key: A Blob of the public key DER. :raises GroupManagerDb.Error: If there's no schedule named scheduleName, if the member's identity name already exists, or other database error. """ scheduleId = self._getScheduleId(scheduleName) if scheduleId == -1: raise GroupManagerDb.Error("The schedule does not exist") # Needs to be changed in the future. memberName = keyName.getPrefix(-1) try: cursor = self._database.cursor() cursor.execute( "INSERT INTO members(schedule_id, member_name, key_name, pubkey) " + "values (?, ?, ?, ?)", ( scheduleId, sqlite3.Binary(bytearray(memberName.wireEncode(TlvWireFormat.get()).buf())), sqlite3.Binary(bytearray(keyName.wireEncode(TlvWireFormat.get()).buf())), sqlite3.Binary(bytearray(key.buf())), ), ) self._database.commit() cursor.close() except Exception as ex: raise GroupManagerDb.Error("Sqlite3GroupManagerDb.addMember: SQLite error: " + str(ex))
def _nfdRegisterPrefix( self, registeredPrefixId, prefix, onInterest, onRegisterFailed, flags, commandKeyChain, commandCertificateName, face): """ Do the work of registerPrefix to register with NFD. :param int registeredPrefixId: The getNextEntryId() which registerPrefix got so it could return it to the caller. If this is 0, then don't add to _registeredPrefixTable (assuming it has already been done). """ if commandKeyChain == None: raise RuntimeError( "registerPrefix: The command KeyChain has not been set. You must call setCommandSigningInfo.") if commandCertificateName.size() == 0: raise RuntimeError( "registerPrefix: The command certificate name has not been set. You must call setCommandSigningInfo.") controlParameters = ControlParameters() controlParameters.setName(prefix) controlParameters.setForwardingFlags(flags) commandInterest = Interest() if self.isLocal(): commandInterest.setName(Name("/localhost/nfd/rib/register")) # The interest is answered by the local host, so set a short timeout. commandInterest.setInterestLifetimeMilliseconds(2000.0) else: commandInterest.setName(Name("/localhop/nfd/rib/register")) # The host is remote, so set a longer timeout. commandInterest.setInterestLifetimeMilliseconds(4000.0) # NFD only accepts TlvWireFormat packets. commandInterest.getName().append(controlParameters.wireEncode(TlvWireFormat.get())) self.makeCommandInterest( commandInterest, commandKeyChain, commandCertificateName, TlvWireFormat.get()) if registeredPrefixId != 0: interestFilterId = 0 if onInterest != None: # registerPrefix was called with the "combined" form that includes # the callback, so add an InterestFilterEntry. interestFilterId = self.getNextEntryId() self.setInterestFilter( interestFilterId, InterestFilter(prefix), onInterest, face) self._registeredPrefixTable.append(Node._RegisteredPrefix( registeredPrefixId, prefix, interestFilterId)) # Send the registration interest. response = Node._RegisterResponse( self, prefix, onInterest, onRegisterFailed, flags, TlvWireFormat.get(), True, face) self.expressInterest( self.getNextEntryId(), commandInterest, response.onData, response.onTimeout, TlvWireFormat.get(), face)
def _nfdRegisterPrefix(self, registeredPrefixId, prefix, onInterest, onRegisterFailed, onRegisterSuccess, registrationOptions, commandKeyChain, commandCertificateName, face): """ Do the work of registerPrefix to register with NFD. :param int registeredPrefixId: The getNextEntryId() which registerPrefix got so it could return it to the caller. If this is 0, then don't add to _registeredPrefixTable (assuming it has already been done). """ if commandKeyChain == None: raise RuntimeError( "registerPrefix: The command KeyChain has not been set. You must call setCommandSigningInfo." ) if commandCertificateName.size() == 0: raise RuntimeError( "registerPrefix: The command certificate name has not been set. You must call setCommandSigningInfo." ) controlParameters = ControlParameters() controlParameters.setName(prefix) controlParameters.setForwardingFlags(registrationOptions) if (registrationOptions.getOrigin() != None and registrationOptions.getOrigin() >= 0): controlParameters.setOrigin(registrationOptions.getOrigin()) # Remove the origin value from the flags since it is not used to encode. controlParameters.getForwardingFlags().setOrigin(None) commandInterest = Interest() commandInterest.setCanBePrefix(True) commandInterest.setMustBeFresh(True) if self.isLocal(): commandInterest.setName(Name("/localhost/nfd/rib/register")) # The interest is answered by the local host, so set a short timeout. commandInterest.setInterestLifetimeMilliseconds(2000.0) else: commandInterest.setName(Name("/localhop/nfd/rib/register")) # The host is remote, so set a longer timeout. commandInterest.setInterestLifetimeMilliseconds(4000.0) # NFD only accepts TlvWireFormat packets. commandInterest.getName().append( controlParameters.wireEncode(TlvWireFormat.get())) self.makeCommandInterest(commandInterest, commandKeyChain, commandCertificateName, TlvWireFormat.get()) # Send the registration interest. response = Node._RegisterResponse(prefix, onRegisterFailed, onRegisterSuccess, registeredPrefixId, self, onInterest, face) self.expressInterest(self.getNextEntryId(), commandInterest, response.onData, response.onTimeout, None, TlvWireFormat.get(), face)
def _nfdRegisterPrefix( self, registeredPrefixId, prefix, onInterest, onRegisterFailed, onRegisterSuccess, registrationOptions, commandKeyChain, commandCertificateName, face): """ Do the work of registerPrefix to register with NFD. :param int registeredPrefixId: The getNextEntryId() which registerPrefix got so it could return it to the caller. If this is 0, then don't add to _registeredPrefixTable (assuming it has already been done). """ if commandKeyChain == None: raise RuntimeError( "registerPrefix: The command KeyChain has not been set. You must call setCommandSigningInfo.") if commandCertificateName.size() == 0: raise RuntimeError( "registerPrefix: The command certificate name has not been set. You must call setCommandSigningInfo.") controlParameters = ControlParameters() controlParameters.setName(prefix) controlParameters.setForwardingFlags(registrationOptions) if (registrationOptions.getOrigin() != None and registrationOptions.getOrigin() >= 0): controlParameters.setOrigin(registrationOptions.getOrigin()) # Remove the origin value from the flags since it is not used to encode. controlParameters.getForwardingFlags().setOrigin(None) commandInterest = Interest() commandInterest.setCanBePrefix(True) if self.isLocal(): commandInterest.setName(Name("/localhost/nfd/rib/register")) # The interest is answered by the local host, so set a short timeout. commandInterest.setInterestLifetimeMilliseconds(2000.0) else: commandInterest.setName(Name("/localhop/nfd/rib/register")) # The host is remote, so set a longer timeout. commandInterest.setInterestLifetimeMilliseconds(4000.0) # NFD only accepts TlvWireFormat packets. commandInterest.getName().append(controlParameters.wireEncode(TlvWireFormat.get())) self.makeCommandInterest( commandInterest, commandKeyChain, commandCertificateName, TlvWireFormat.get()) # Send the registration interest. response = Node._RegisterResponse( prefix, onRegisterFailed, onRegisterSuccess, registeredPrefixId, self, onInterest, face) self.expressInterest( self.getNextEntryId(), commandInterest, response.onData, response.onTimeout, None, TlvWireFormat.get(), face)
def listAllMembers(self): """ List all the members. :return: A new List of Name with the names of all members. :rtype: Array<Name> :raises GroupManagerDb.Error: For a database error. """ list = [] try: cursor = self._database.cursor() cursor.execute("SELECT member_name FROM members", ()) results = cursor.fetchall() for (nameEncoding, ) in results: identity = Name() identity.wireDecode(bytearray(nameEncoding), TlvWireFormat.get()) list.append(identity) cursor.close() return list except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.listAllMembers: SQLite error: " + str(ex))
def hasMember(self, identity): """ Check if there is a member with the given identity name. :param Name identity: The member's identity name. :return: True if there is a member. :rtype: bool :raises GroupManagerDb.Error: For a database error. """ result = False try: cursor = self._database.cursor() cursor.execute( "SELECT member_id FROM members WHERE member_name=?", (sqlite3.Binary( bytearray(identity.wireEncode( TlvWireFormat.get()).buf())), )) if cursor.fetchone() != None: result = True cursor.close() return result except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.hasMember: SQLite error: " + str(ex))
def hasEKey(self, eKeyName): """ Check if there is an EKey with the name eKeyName in the database. :param Name eKeyName: The name of the EKey. :return: True if the EKey exists. :rtype: bool :raises GroupManagerDb.Error: For a database error. """ result = False try: cursor = self._database.cursor() cursor.execute( "SELECT ekey_id FROM ekeys where ekey_name=?", (sqlite3.Binary( bytearray(eKeyName.wireEncode( TlvWireFormat.get()).buf())), )) if cursor.fetchone() != None: result = True cursor.close() return result except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.hasEKey: SQLite error: " + str(ex))
def updateMemberSchedule(self, identity, scheduleName): """ Change the name of the schedule for the given member's identity name. :param Name identity: The member's identity name. :param str scheduleName: The new schedule name. :raises GroupManagerDb.Error: If there's no member with the given identity name in the database, or there's no schedule named scheduleName, or other database error. """ scheduleId = self._getScheduleId(scheduleName) if scheduleId == -1: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.updateMemberSchedule: The schedule does not exist"); try: cursor = self._database.cursor() cursor.execute( "UPDATE members SET schedule_id=? WHERE member_name=?", (scheduleId, sqlite3.Binary(bytearray(identity.wireEncode(TlvWireFormat.get()).buf())))) self._database.commit() cursor.close() except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.updateMemberSchedule: SQLite error: " + str(ex))
def wireDecode(self, input): """ Decode the input as an NDN-TLV SafeBag and update this object. :param input: The array with the bytes to decode. :type input: A Blob or an array type with int elements """ if isinstance(input, Blob): input = input.buf() # Decode directly as TLV. We don't support the WireFormat abstraction # because this isn't meant to go directly on the wire. decoder = TlvDecoder(input) endOffset = decoder.readNestedTlvsStart(Tlv.SafeBag_SafeBag) # Get the bytes of the certificate and decode. certificateBeginOffset = decoder.getOffset() certificateEndOffset = decoder.readNestedTlvsStart(Tlv.Data) decoder.seek(certificateEndOffset) self._certificate = Data() self._certificate.wireDecode( decoder.getSlice(certificateBeginOffset, certificateEndOffset), TlvWireFormat.get()) self._privateKeyBag = Blob( decoder.readBlobTlv(Tlv.SafeBag_EncryptedKeyBag), True) decoder.finishNestedTlvs(endOffset)
def getKey(self, keyName): """ Get the key with keyName from the database. :param Name keyName: The key name. :return: A Blob with the encoded key, or an isNull Blob if cannot find the key with keyName. :rtype: Blob :raises ConsumerDb.Error: For a database error. """ try: cursor = self._database.cursor() cursor.execute( "SELECT key_buf FROM decryptionkeys WHERE key_name=?", (sqlite3.Binary( bytearray(keyName.wireEncode( TlvWireFormat.get()).buf())), )) result = cursor.fetchone() key = Blob() if result != None: return Blob(bytearray(result[0]), False) cursor.close() return key except Exception as ex: raise ConsumerDb.Error("Sqlite3ConsumerDb.getKey: SQLite error: " + str(ex))
def getEKey(self, eKeyName): """ Get the group key pair with the name eKeyName from the database. :param Name eKeyName: The name of the EKey. :return: A tuple (privateKeyBlob, publicKeyBlob) where "privateKeyBlob" is the encoding Blob of the private key and "publicKeyBlob" is the encoding Blob of the public key. :rtype: (Blob, Blob) :raises GroupManagerDb.Error: If the key with name eKeyName does not exist in the database, or other database error. """ publicKey = None try: cursor = self._database.cursor() cursor.execute( "SELECT pub_key FROM ekeys where ekey_name=?", (sqlite3.Binary(bytearray(eKeyName.wireEncode(TlvWireFormat.get()).buf())), )) result = cursor.fetchone() if result != None: publicKey = Blob(bytearray(result[0]), False) cursor.close() except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.getMemberSchedule: SQLite error: " + str(ex)) if publicKey == None: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.getEKey: Cannot get the result from the database") return (publicKey, self._privateKeyBase[Name(eKeyName)])
def getScheduleMembers(self, name): """ For each member using the given schedule, get the name and public key DER of the member's key. :param str name: The name of the schedule. :return: a new dictionary where the dictionary's key is the Name of the public key and the value is the Blob of the public key DER. Note that the member's identity name is keyName.getPrefix(-1). If the schedule name is not found, the dictionary is empty. :rtype: dictionary<Name, Blob> :raises GroupManagerDb.Error: For a database error. """ dictionary = {} try: cursor = self._database.cursor() cursor.execute( "SELECT key_name, pubkey " + "FROM members JOIN schedules ON members.schedule_id=schedules.schedule_id " + "WHERE schedule_name=?", (name, )) results = cursor.fetchall() for (keyNameEncoding, keyEncoding) in results: keyName = Name() keyName.wireDecode(bytearray(keyNameEncoding), TlvWireFormat.get()) dictionary[keyName] = Blob(bytearray(keyEncoding), False) cursor.close() return dictionary except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.getScheduleMembers: SQLite error: " + str(ex))
def getScheduleMembers(self, name): """ For each member using the given schedule, get the name and public key DER of the member's key. :param str name: The name of the schedule. :return: a new dictionary where the dictionary's key is the Name of the public key and the value is the Blob of the public key DER. Note that the member's identity name is keyName.getPrefix(-1). If the schedule name is not found, the dictionary is empty. :rtype: dictionary<Name, Blob> :raises GroupManagerDb.Error: For a database error. """ dictionary = {} try: cursor = self._database.cursor() cursor.execute( "SELECT key_name, pubkey " + "FROM members JOIN schedules ON members.schedule_id=schedules.schedule_id " + "WHERE schedule_name=?", (name,), ) results = cursor.fetchall() for (keyNameEncoding, keyEncoding) in results: keyName = Name() keyName.wireDecode(bytearray(keyNameEncoding), TlvWireFormat.get()) dictionary[keyName] = Blob(bytearray(keyEncoding), False) cursor.close() return dictionary except Exception as ex: raise GroupManagerDb.Error("Sqlite3GroupManagerDb.getScheduleMembers: SQLite error: " + str(ex))
def onData(self, interest, responseData): """ We received the response. """ # Decode responseData.getContent() and check for a success code. controlResponse = ControlResponse() try: controlResponse.wireDecode(responseData.getContent(), TlvWireFormat.get()) except ValueError as ex: logging.getLogger(__name__).info( "Register prefix failed: Error decoding the NFD response: %s", str(ex)) try: self._onRegisterFailed(self._prefix) except: logging.exception("Error in onRegisterFailed") return # Status code 200 is "OK". if controlResponse.getStatusCode() != 200: logging.getLogger(__name__).info( "Register prefix failed: Expected NFD status code 200, got: %d", controlResponse.getStatusCode()) try: self._onRegisterFailed(self._prefix) except: logging.exception("Error in onRegisterFailed") return # Success, so we can add to the registered prefix table. if self._registeredPrefixId != 0: interestFilterId = 0 if self._onInterest != None: # registerPrefix was called with the "combined" form that includes # the callback, so add an InterestFilterEntry. interestFilterId = self._parent.getNextEntryId() self._parent.setInterestFilter( interestFilterId, InterestFilter(self._prefix), self._onInterest, self._face) if not self._parent._registeredPrefixTable.add( self._registeredPrefixId, self._prefix, interestFilterId): # removeRegisteredPrefix was already called with the registeredPrefixId. if interestFilterId > 0: # Remove the related interest filter we just added. self._parent.unsetInterestFilter(interestFilterId) return logging.getLogger(__name__).info( "Register prefix succeeded with the NFD forwarder for prefix %s", self._prefix.toUri()) if self._onRegisterSuccess != None: try: self._onRegisterSuccess(self._prefix, self._registeredPrefixId) except: logging.exception("Error in onRegisterSuccess")
def getMemberSchedule(self, identity): """ Get the name of the schedule for the given member's identity name. :param Name identity: The member's identity name. :return: The name of the schedule. :rtype: str :raises GroupManagerDb.Error: If there's no member with the given identity name in the database, or other database error. """ scheduleName = None try: cursor = self._database.cursor() cursor.execute( "SELECT schedule_name " + "FROM schedules JOIN members ON schedules.schedule_id = members.schedule_id " + "WHERE member_name=?", (sqlite3.Binary(bytearray(identity.wireEncode(TlvWireFormat.get()).buf())), )) result = cursor.fetchone() if result != None: scheduleName = result[0] cursor.close() except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.getMemberSchedule: SQLite error: " + str(ex)) if scheduleName == None: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.getMemberSchedule: Cannot get the result from the database") return scheduleName
def getKey(self, keyName): """ Get the key with keyName from the database. :param Name keyName: The key name. :return: A Blob with the encoded key, or an isNull Blob if cannot find the key with keyName. :rtype: Blob :raises ConsumerDb.Error: For a database error. """ try: cursor = self._database.cursor() cursor.execute( "SELECT key_buf FROM decryptionkeys WHERE key_name=?", (sqlite3.Binary(bytearray(keyName.wireEncode(TlvWireFormat.get()).buf())), )) result = cursor.fetchone() key = Blob() if result != None: return Blob(bytearray(result[0]), False) cursor.close() return key except Exception as ex: raise ConsumerDb.Error( "Sqlite3ConsumerDb.getKey: SQLite error: " + str(ex))
def getMemberSchedule(self, identity): """ Get the name of the schedule for the given member's identity name. :param Name identity: The member's identity name. :return: The name of the schedule. :rtype: str :raises GroupManagerDb.Error: If there's no member with the given identity name in the database, or other database error. """ scheduleName = None try: cursor = self._database.cursor() cursor.execute( "SELECT schedule_name " + "FROM schedules JOIN members ON schedules.schedule_id = members.schedule_id " + "WHERE member_name=?", (sqlite3.Binary(bytearray(identity.wireEncode(TlvWireFormat.get()).buf())),), ) result = cursor.fetchone() if result != None: scheduleName = result[0] cursor.close() except Exception as ex: raise GroupManagerDb.Error("Sqlite3GroupManagerDb.getMemberSchedule: SQLite error: " + str(ex)) if scheduleName == None: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.getMemberSchedule: Cannot get the result from the database" ) return scheduleName
def _nfdRegisterPrefix(self, registeredPrefixId, prefix, onInterest, onRegisterFailed, flags, commandKeyChain, commandCertificateName): """ Do the work of registerPrefix to register with NFD. :param int registeredPrefixId: The _RegisteredPrefix.getNextRegisteredPrefixId() which registerPrefix got so it could return it to the caller. If this is 0, then don't add to registeredPrefixTable_ (assuming it has already been done). """ if commandKeyChain == None: raise RuntimeError( "registerPrefix: The command KeyChain has not been set. You must call setCommandSigningInfo." ) if commandCertificateName.size() == 0: raise RuntimeError( "registerPrefix: The command certificate name has not been set. You must call setCommandSigningInfo." ) controlParameters = ControlParameters() controlParameters.setName(prefix) commandInterest = Interest(Name("/localhost/nfd/rib/register")) # NFD only accepts TlvWireFormat packets. commandInterest.getName().append( controlParameters.wireEncode(TlvWireFormat.get())) self.makeCommandInterest(commandInterest, commandKeyChain, commandCertificateName, TlvWireFormat.get()) # The interest is answered by the local host, so set a short timeout. commandInterest.setInterestLifetimeMilliseconds(2000.0) if registeredPrefixId != 0: # Save the onInterest callback and send the registration interest. self._registeredPrefixTable.append( Node._RegisteredPrefix(registeredPrefixId, prefix, onInterest)) response = Node._RegisterResponse(self, prefix, onInterest, onRegisterFailed, flags, TlvWireFormat.get(), True) self.expressInterest(commandInterest, response.onData, response.onTimeout, TlvWireFormat.get())
def _nfdRegisterPrefix( self, registeredPrefixId, prefix, onInterest, onRegisterFailed, flags, commandKeyChain, commandCertificateName): """ Do the work of registerPrefix to register with NFD. :param int registeredPrefixId: The _RegisteredPrefix.getNextRegisteredPrefixId() which registerPrefix got so it could return it to the caller. If this is 0, then don't add to _registeredPrefixTable (assuming it has already been done). """ if commandKeyChain == None: raise RuntimeError( "registerPrefix: The command KeyChain has not been set. You must call setCommandSigningInfo.") if commandCertificateName.size() == 0: raise RuntimeError( "registerPrefix: The command certificate name has not been set. You must call setCommandSigningInfo.") controlParameters = ControlParameters() controlParameters.setName(prefix) commandInterest = Interest(Name("/localhost/nfd/rib/register")) # NFD only accepts TlvWireFormat packets. commandInterest.getName().append(controlParameters.wireEncode(TlvWireFormat.get())) self.makeCommandInterest( commandInterest, commandKeyChain, commandCertificateName, TlvWireFormat.get()) # The interest is answered by the local host, so set a short timeout. commandInterest.setInterestLifetimeMilliseconds(2000.0) if registeredPrefixId != 0: # Save the onInterest callback and send the registration interest. self._registeredPrefixTable.append(Node._RegisteredPrefix( registeredPrefixId, prefix, onInterest)) response = Node._RegisterResponse( self, prefix, onInterest, onRegisterFailed, flags, TlvWireFormat.get(), True) self.expressInterest( commandInterest, response.onData, response.onTimeout, TlvWireFormat.get())
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ # The type codes for TLV Interest and Data packets are chosen to not # conflict with the first byte of a binary XML packet, so we canjust # look at the first byte. if not (element[0] == Tlv.Interest or element[0] == Tlv.Data): # Ignore non-TLV elements. return # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) # Now process as Interest or Data. if interest != None: entry = self._getEntryForRegisteredPrefix(interest.getName()) if entry != None: entry.getOnInterest()(entry.getPrefix(), interest, self._transport, entry.getRegisteredPrefixId()) elif data != None: pendingInterests = self._extractEntriesForExpressedInterest( data.getName()) for pendingInterest in pendingInterests: pendingInterest.getOnData()(pendingInterest.getInterest(), data)
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ # The type codes for TLV Interest and Data packets are chosen to not # conflict with the first byte of a binary XML packet, so we canjust # look at the first byte. if not (element[0] == Tlv.Interest or element[0] == Tlv.Data): # Ignore non-TLV elements. return # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) # Now process as Interest or Data. if interest != None: entry = self._getEntryForRegisteredPrefix(interest.getName()) if entry != None: entry.getOnInterest()( entry.getPrefix(), interest, self._transport, entry.getRegisteredPrefixId()) elif data != None: pendingInterests = self._extractEntriesForExpressedInterest( data.getName()) for pendingInterest in pendingInterests: pendingInterest.getOnData()(pendingInterest.getInterest(), data)
def deleteMember(self, identity): """ Delete a member with the given identity name. If there is no member with the identity name, then do nothing. :param Name identity: The member's identity name. :raises GroupManagerDb.Error: For a database error. """ try: cursor = self._database.cursor() cursor.execute( "DELETE FROM members WHERE member_name=?", (sqlite3.Binary(bytearray(identity.wireEncode(TlvWireFormat.get()).buf())),), ) self._database.commit() cursor.close() except Exception as ex: raise GroupManagerDb.Error("Sqlite3GroupManagerDb.deleteMember: SQLite error: " + str(ex))
def deleteKey(self, keyName): """ Delete the key with keyName from the database. If there is no key with keyName, do nothing. :param Name keyName: The key name. :raises ConsumerDb.Error: For a database error. """ try: cursor = self._database.cursor() cursor.execute( "DELETE FROM decryptionkeys WHERE key_name=?", (sqlite3.Binary(bytearray(keyName.wireEncode(TlvWireFormat.get()).buf())), )) self._database.commit() cursor.close() except Exception as ex: raise ConsumerDb.Error( "Sqlite3ConsumerDb.deleteKey: SQLite error: " + str(ex))
def deleteMember(self, identity): """ Delete a member with the given identity name. If there is no member with the identity name, then do nothing. :param Name identity: The member's identity name. :raises GroupManagerDb.Error: For a database error. """ try: cursor = self._database.cursor() cursor.execute( "DELETE FROM members WHERE member_name=?", (sqlite3.Binary(bytearray(identity.wireEncode(TlvWireFormat.get()).buf())), )) self._database.commit() cursor.close() except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.deleteMember: SQLite error: " + str(ex))
def deleteEKey(self, eKeyName): """ Delete the EKey with name eKeyName from the database. If no key with the name exists in the database, do nothing. :param Name eKeyName: The name of the EKey. :raises GroupManagerDb.Error: For a database error. """ try: cursor = self._database.cursor() cursor.execute( "DELETE FROM ekeys WHERE ekey_name=?", (sqlite3.Binary(bytearray(eKeyName.wireEncode(TlvWireFormat.get()).buf())), )) self._database.commit() cursor.close() except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.deleteEKey: SQLite error: " + str(ex)) del self._privateKeyBase[eKeyName]
def addKey(self, keyName, keyBlob): """ Add the key with keyName and keyBlob to the database. :param Name keyName: The key name. :param Blob keyBlob: The encoded key. :raises ConsumerDb.Error: If a key with the same keyName already exists in the database, or other database error. """ try: cursor = self._database.cursor() cursor.execute( "INSERT INTO decryptionkeys(key_name, key_buf) values (?, ?)", (sqlite3.Binary(bytearray(keyName.wireEncode(TlvWireFormat.get()).buf())), sqlite3.Binary(bytearray(keyBlob.buf())))) self._database.commit() cursor.close() except Exception as ex: raise ConsumerDb.Error( "Sqlite3ConsumerDb.addKey: SQLite error: " + str(ex))
def _encodeLpNack(interest, networkNack): """ Encode the interest into an NDN-TLV LpPacket as a NACK with the reason code in the networkNack object. TODO: Generalize this and move to WireFormat.encodeLpPacket. :param Interest interest: The Interest to put in the LpPacket fragment. :param NetworkNack networkNack: The NetworkNack with the reason code. :return: A Blob containing the encoding. :rtype: Blob """ encoder = TlvEncoder(256) saveLength = len(encoder) # Encode backwards. # Encode the fragment with the Interest. encoder.writeBlobTlv( Tlv.LpPacket_Fragment, interest.wireEncode(TlvWireFormat.get()).buf()) # Encode the reason. if (networkNack.getReason() == NetworkNack.Reason.NONE or networkNack.getReason() == NetworkNack.Reason.CONGESTION or networkNack.getReason() == NetworkNack.Reason.DUPLICATE or networkNack.getReason() == NetworkNack.Reason.NO_ROUTE): # The Reason enum is set up with the correct integer for each NDN-TLV Reason. reason = networkNack.getReason() elif networkNack.getReason() == NetworkNack.Reason.OTHER_CODE: reason = networkNack.getOtherReasonCode() else: # We don't expect this to happen. raise RuntimeError("unrecognized NetworkNack.getReason() value") nackSaveLength = len(encoder) encoder.writeNonNegativeIntegerTlv(Tlv.LpPacket_NackReason, reason) encoder.writeTypeAndLength( Tlv.LpPacket_Nack, len(encoder) - nackSaveLength) encoder.writeTypeAndLength( Tlv.LpPacket_LpPacket, len(encoder) - saveLength) return Blob(encoder.getOutput(), False)
def _encodeLpNack(interest, networkNack): """ Encode the interest into an NDN-TLV LpPacket as a NACK with the reason code in the networkNack object. TODO: Generalize this and move to WireFormat.encodeLpPacket. :param Interest interest: The Interest to put in the LpPacket fragment. :param NetworkNack networkNack: The NetworkNack with the reason code. :return: A Blob containing the encoding. :rtype: Blob """ encoder = TlvEncoder(256) saveLength = len(encoder) # Encode backwards. # Encode the fragment with the Interest. encoder.writeBlobTlv(Tlv.LpPacket_Fragment, interest.wireEncode(TlvWireFormat.get()).buf()) # Encode the reason. if (networkNack.getReason() == NetworkNack.Reason.NONE or networkNack.getReason() == NetworkNack.Reason.CONGESTION or networkNack.getReason() == NetworkNack.Reason.DUPLICATE or networkNack.getReason() == NetworkNack.Reason.NO_ROUTE): # The Reason enum is set up with the correct integer for each NDN-TLV Reason. reason = networkNack.getReason() elif networkNack.getReason() == NetworkNack.Reason.OTHER_CODE: reason = networkNack.getOtherReasonCode() else: # We don't expect this to happen. raise RuntimeError("unrecognized NetworkNack.getReason() value") nackSaveLength = len(encoder) encoder.writeNonNegativeIntegerTlv(Tlv.LpPacket_NackReason, reason) encoder.writeTypeAndLength(Tlv.LpPacket_Nack, len(encoder) - nackSaveLength) encoder.writeTypeAndLength(Tlv.LpPacket_LpPacket, len(encoder) - saveLength) return Blob(encoder.getOutput(), False)
def onData(self, interest, responseData): """ We received the response. Do a quick check of expected name components. """ # Decode responseData.getContent() and check for a success code. controlResponse = ControlResponse() try: controlResponse.wireDecode(responseData.getContent(), TlvWireFormat.get()) except ValueError as ex: logging.getLogger(__name__).info( "Register prefix failed: Error decoding the NFD response: %s", str(ex)) try: self._onRegisterFailed(self._prefix) except: logging.exception("Error in onRegisterFailed") return # Status code 200 is "OK". if controlResponse.getStatusCode() != 200: logging.getLogger(__name__).info( "Register prefix failed: Expected NFD status code 200, got: %d", controlResponse.getStatusCode()) try: self._onRegisterFailed(self._prefix) except: logging.exception("Error in onRegisterFailed") return logging.getLogger(__name__).info( "Register prefix succeeded with the NFD forwarder for prefix %s", self._prefix.toUri()) if self._onRegisterSuccess != None: try: self._onRegisterSuccess(self._prefix, self._registeredPrefixId) except: logging.exception("Error in onRegisterSuccess")
def wireEncode(self, wireFormat=None): """ Encode this as an NDN-TLV SafeBag. :return: The encoded byte array as a Blob. :rtype: Blob """ # Encode directly as TLV. We don't support the WireFormat abstraction # because this isn't meant to go directly on the wire. encoder = TlvEncoder(256) saveLength = len(encoder) # Encode backwards. encoder.writeBlobTlv(Tlv.SafeBag_EncryptedKeyBag, self._privateKeyBag.buf()) # Add the entire Data packet encoding as is. encoder.writeBuffer( self._certificate.wireEncode(TlvWireFormat.get()).buf()) encoder.writeTypeAndLength(Tlv.SafeBag_SafeBag, len(encoder) - saveLength) return Blob(encoder.getOutput(), False)
def addEKey(self, eKeyName, publicKey, privateKey): """ Add the EKey with name eKeyName to the database. :param Name eKeyName: The name of the EKey. This copies the Name. :param Blob publicKey: The encoded public key of the group key pair. :param Blob privateKey: The encoded private key of the group key pair. :raises GroupManagerDb.Error: If a key with name eKeyName already exists in the database, or other database error. """ try: cursor = self._database.cursor() cursor.execute( "INSERT INTO ekeys(ekey_name, pub_key) values (?, ?)", (sqlite3.Binary(bytearray(eKeyName.wireEncode(TlvWireFormat.get()).buf())), sqlite3.Binary(bytearray(publicKey.buf())))) self._database.commit() cursor.close() except Exception as ex: raise GroupManagerDb.Error( "Sqlite3GroupManagerDb.addEKey: SQLite error: " + str(ex)) self._privateKeyBase[Name(eKeyName)] = privateKey
def listAllMembers(self): """ List all the members. :return: A new List of Name with the names of all members. :rtype: Array<Name> :raises GroupManagerDb.Error: For a database error. """ list = [] try: cursor = self._database.cursor() cursor.execute("SELECT member_name FROM members", ()) results = cursor.fetchall() for (nameEncoding,) in results: identity = Name() identity.wireDecode(bytearray(nameEncoding), TlvWireFormat.get()) list.append(identity) cursor.close() return list except Exception as ex: raise GroupManagerDb.Error("Sqlite3GroupManagerDb.listAllMembers: SQLite error: " + str(ex))
def wireEncode(self, wireFormat = None): """ Encode this as an NDN-TLV SafeBag. :return: The encoded byte array as a Blob. :rtype: Blob """ # Encode directly as TLV. We don't support the WireFormat abstraction # because this isn't meant to go directly on the wire. encoder = TlvEncoder(256) saveLength = len(encoder) # Encode backwards. encoder.writeBlobTlv( Tlv.SafeBag_EncryptedKeyBag, self._privateKeyBag.buf()) # Add the entire Data packet encoding as is. encoder.writeBuffer( self._certificate.wireEncode(TlvWireFormat.get()).buf()) encoder.writeTypeAndLength( Tlv.SafeBag_SafeBag, len(encoder) - saveLength) return Blob(encoder.getOutput(), False)
def hasMember(self, identity): """ Check if there is a member with the given identity name. :param Name identity: The member's identity name. :return: True if there is a member. :rtype: bool :raises GroupManagerDb.Error: For a database error. """ result = False try: cursor = self._database.cursor() cursor.execute( "SELECT member_id FROM members WHERE member_name=?", (sqlite3.Binary(bytearray(identity.wireEncode(TlvWireFormat.get()).buf())),), ) if cursor.fetchone() != None: result = True cursor.close() return result except Exception as ex: raise GroupManagerDb.Error("Sqlite3GroupManagerDb.hasMember: SQLite error: " + str(ex))
def encryptData(data, payload, keyName, key, params): """ Prepare an encrypted data packet by encrypting the payload using the key according to the params. In addition, this prepares the encoded EncryptedContent with the encryption result using keyName and params. The encoding is set as the content of the data packet. If params defines an asymmetric encryption algorithm and the payload is larger than the maximum plaintext size, this encrypts the payload with a symmetric key that is asymmetrically encrypted and provided as a nonce in the content of the data packet. The packet's <dataName>/ is updated to be <dataName>/FOR/<keyName> :param Data data: The data packet which is updated. :param Blob payload: The payload to encrypt. :param Name keyName: The key name for the EncryptedContent. :param Blob key: The encryption key value. :param EncryptParams params: The parameters for encryption. """ data.getName().append(Encryptor.NAME_COMPONENT_FOR).append(keyName) algorithmType = params.getAlgorithmType() if (algorithmType == EncryptAlgorithmType.AesCbc or algorithmType == EncryptAlgorithmType.AesEcb): content = Encryptor._encryptSymmetric(payload, key, keyName, params) data.setContent(content.wireEncode(TlvWireFormat.get())) elif (algorithmType == EncryptAlgorithmType.RsaPkcs or algorithmType == EncryptAlgorithmType.RsaOaep): # Cryptography doesn't have a direct way to get the maximum plain text # size, so try to encrypt the payload first and catch the error if # it is too big. try: content = Encryptor._encryptAsymmetric(payload, key, keyName, params) data.setContent(content.wireEncode(TlvWireFormat.get())) return except ValueError as ex: message = ex.args[0] if not ("Data too long for key size" in message): raise ex # Else the payload is larger than the maximum plaintext size. Continue. # 128-bit nonce. nonceKeyBuffer = bytearray(16) for i in range(16): nonceKeyBuffer[i] = _systemRandom.randint(0, 0xff) nonceKey = Blob(nonceKeyBuffer, False) nonceKeyName = Name(keyName) nonceKeyName.append("nonce") symmetricParams = EncryptParams(EncryptAlgorithmType.AesCbc, AesAlgorithm.BLOCK_SIZE) nonceContent = Encryptor._encryptSymmetric(payload, nonceKey, nonceKeyName, symmetricParams) payloadContent = Encryptor._encryptAsymmetric( nonceKey, key, keyName, params) nonceContentEncoding = nonceContent.wireEncode() payloadContentEncoding = payloadContent.wireEncode() content = bytearray(nonceContentEncoding.size() + payloadContentEncoding.size()) content[0:payloadContentEncoding.size( )] = payloadContentEncoding.buf() content[payloadContentEncoding.size():] = nonceContentEncoding.buf( ) data.setContent(Blob(content, False)) else: raise RuntimeError("Unsupported encryption method")
def encryptData(data, payload, keyName, key, params): """ Prepare an encrypted data packet by encrypting the payload using the key according to the params. In addition, this prepares the encoded EncryptedContent with the encryption result using keyName and params. The encoding is set as the content of the data packet. If params defines an asymmetric encryption algorithm and the payload is larger than the maximum plaintext size, this encrypts the payload with a symmetric key that is asymmetrically encrypted and provided as a nonce in the content of the data packet. The packet's <dataName>/ is updated to be <dataName>/FOR/<keyName> :param Data data: The data packet which is updated. :param Blob payload: The payload to encrypt. :param Name keyName: The key name for the EncryptedContent. :param Blob key: The encryption key value. :param EncryptParams params: The parameters for encryption. """ data.getName().append(Encryptor.NAME_COMPONENT_FOR).append(keyName) algorithmType = params.getAlgorithmType() if (algorithmType == EncryptAlgorithmType.AesCbc or algorithmType == EncryptAlgorithmType.AesEcb): content = Encryptor._encryptSymmetric(payload, key, keyName, params) data.setContent(content.wireEncode(TlvWireFormat.get())) elif (algorithmType == EncryptAlgorithmType.RsaPkcs or algorithmType == EncryptAlgorithmType.RsaOaep): # Cryptography doesn't have a direct way to get the maximum plain text # size, so try to encrypt the payload first and catch the error if # it is too big. try: content = Encryptor._encryptAsymmetric(payload, key, keyName, params) data.setContent(content.wireEncode(TlvWireFormat.get())) return except ValueError as ex: message = ex.args[0] if not ("Data too long for key size" in message): raise ex # Else the payload is larger than the maximum plaintext size. Continue. # 128-bit nonce. nonceKeyBuffer = bytearray(16) for i in range(16): nonceKeyBuffer[i] = _systemRandom.randint(0, 0xff) nonceKey = Blob(nonceKeyBuffer, False) nonceKeyName = Name(keyName) nonceKeyName.append("nonce") symmetricParams = EncryptParams( EncryptAlgorithmType.AesCbc, AesAlgorithm.BLOCK_SIZE) nonceContent = Encryptor._encryptSymmetric( payload, nonceKey, nonceKeyName, symmetricParams) payloadContent = Encryptor._encryptAsymmetric( nonceKey, key, keyName, params) nonceContentEncoding = nonceContent.wireEncode() payloadContentEncoding = payloadContent.wireEncode() content = bytearray( nonceContentEncoding.size() + payloadContentEncoding.size()) content[0:payloadContentEncoding.size()] = payloadContentEncoding.buf() content[payloadContentEncoding.size():] = nonceContentEncoding.buf() data.setContent(Blob(content, False)) else: raise RuntimeError("Unsupported encryption method")
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ lpPacket = None if element[0] == Tlv.LpPacket_LpPacket: # Decode the LpPacket and replace element with the fragment. lpPacket = LpPacket() # Set copy False so that the fragment is a slice which will be # copied below. The header fields are all integers and don't need to # be copied. TlvWireFormat.get().decodeLpPacket(lpPacket, element, False) element = lpPacket.getFragmentWireEncoding().buf() # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: interest.setLpPacket(lpPacket) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: data.setLpPacket(lpPacket) if lpPacket != None: # We have decoded the fragment, so remove the wire encoding to save # memory. lpPacket.setFragmentWireEncoding(Blob()) networkNack = NetworkNack.getFirstHeader(lpPacket) if networkNack != None: if interest == None: # We got a Nack but not for an Interest, so drop the packet. return pendingInterests = [] self._pendingInterestTable.extractEntriesForNackInterest( interest, pendingInterests) for pendingInterest in pendingInterests: try: pendingInterest.getOnNetworkNack()( pendingInterest.getInterest(), networkNack) except: logging.exception("Error in onNetworkNack") # We have processed the network Nack packet. return # Now process as Interest or Data. if interest != None: self._dispatchInterest(interest) elif data != None: self._satisfyPendingInterests(data)
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ lpPacket = None if element[0] == Tlv.LpPacket_LpPacket: # Decode the LpPacket and replace element with the fragment. lpPacket = LpPacket() # Set copy False so that the fragment is a slice which will be # copied below. The header fields are all integers and don't need to # be copied. TlvWireFormat.get().decodeLpPacket(lpPacket, element, False) element = lpPacket.getFragmentWireEncoding().buf() # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: interest.setLpPacket(lpPacket) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: data.setLpPacket(lpPacket) if lpPacket != None: # We have decoded the fragment, so remove the wire encoding to save # memory. lpPacket.setFragmentWireEncoding(Blob()) networkNack = NetworkNack.getFirstHeader(lpPacket) if networkNack != None: if interest == None: # We got a Nack but not for an Interest, so drop the packet. return pendingInterests = [] self._pendingInterestTable.extractEntriesForNackInterest( interest, pendingInterests) for pendingInterest in pendingInterests: try: pendingInterest.getOnNetworkNack()( pendingInterest.getInterest(), networkNack) except: logging.exception("Error in onNetworkNack") # We have processed the network Nack packet. return # Now process as Interest or Data. if interest != None: # Call all interest filter callbacks which match. matchedFilters = [] self._interestFilterTable.getMatchedFilters( interest, matchedFilters) for i in range(len(matchedFilters)): entry = matchedFilters[i] includeFilter = True onInterestCall = entry.getOnInterest() # If onInterest is not a function nor a method assumes it is a # calleable object if (not inspect.isfunction(onInterestCall) and not inspect.ismethod(onInterestCall)): onInterestCall = onInterestCall.__call__ # Use getcallargs to test if onInterest accepts 5 args. try: inspect.getcallargs(onInterestCall, None, None, None, None, None) except TypeError: # Assume onInterest is old-style with 4 arguments. includeFilter = False if includeFilter: try: entry.getOnInterest()(entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId(), entry.getFilter()) except: logging.exception("Error in onInterest") else: # Old-style onInterest without the filter argument. We # still pass a Face instead of Transport since Face also # has a send method. try: entry.getOnInterest()(entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId()) except: logging.exception("Error in onInterest") elif data != None: pendingInterests = [] self._pendingInterestTable.extractEntriesForExpressedInterest( data, pendingInterests) for pendingInterest in pendingInterests: try: pendingInterest.getOnData()(pendingInterest.getInterest(), data) except: logging.exception("Error in onData")
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ # The type codes for TLV Interest and Data packets are chosen to not # conflict with the first byte of a binary XML packet, so we canjust # look at the first byte. if not (element[0] == Tlv.Interest or element[0] == Tlv.Data): # Ignore non-TLV elements. # Assume it is Binary XML. if not WireFormat.ENABLE_NDNX: raise RuntimeError( "BinaryXmlWireFormat (NDNx) is deprecated. To enable while you upgrade your network to use NDN-TLV, set WireFormat.ENABLE_NDNX = True") return # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) # Now process as Interest or Data. if interest != None: # Call all interest filter callbacks which match. for i in range(len(self._interestFilterTable)): entry = self._interestFilterTable[i] if entry.getFilter().doesMatch(interest.getName()): includeFilter = True # Use getcallargs to test if onInterest accepts 5 args. try: inspect.getcallargs(entry.getOnInterest(), None, None, None, None, None) except TypeError: # Assume onInterest is old-style with 4 arguments. includeFilter = False if includeFilter: entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId(), entry.getFilter()) else: # Old-style onInterest without the filter argument. We # still pass a Face instead of Transport since Face also # has a send method. entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId()) elif data != None: pendingInterests = self._extractEntriesForExpressedInterest( data.getName()) for pendingInterest in pendingInterests: pendingInterest.getOnData()(pendingInterest.getInterest(), data)
def onReceivedElement(self, element): """ This is called by the transport's ElementReader to process an entire received Data or Interest element. :param element: The bytes of the incoming element. :type element: An array type with int elements """ lpPacket = None if element[0] == Tlv.LpPacket_LpPacket: # Decode the LpPacket and replace element with the fragment. lpPacket = LpPacket() # Set copy False so that the fragment is a slice which will be # copied below. The header fields are all integers and don't need to # be copied. TlvWireFormat.get().decodeLpPacket(lpPacket, element, False) element = lpPacket.getFragmentWireEncoding().buf() # First, decode as Interest or Data. interest = None data = None decoder = TlvDecoder(element) if decoder.peekType(Tlv.Interest, len(element)): interest = Interest() interest.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: interest.setLpPacket(lpPacket) elif decoder.peekType(Tlv.Data, len(element)): data = Data() data.wireDecode(element, TlvWireFormat.get()) if lpPacket != None: data.setLpPacket(lpPacket) if lpPacket != None: # We have decoded the fragment, so remove the wire encoding to save # memory. lpPacket.setFragmentWireEncoding(Blob()) networkNack = NetworkNack.getFirstHeader(lpPacket) if networkNack != None: if interest == None: # We got a Nack but not for an Interest, so drop the packet. return pendingInterests = [] self._pendingInterestTable.extractEntriesForNackInterest( interest, pendingInterests) for pendingInterest in pendingInterests: try: pendingInterest.getOnNetworkNack()( pendingInterest.getInterest(), networkNack) except: logging.exception("Error in onNetworkNack") # We have processed the network Nack packet. return # Now process as Interest or Data. if interest != None: # Call all interest filter callbacks which match. matchedFilters = [] self._interestFilterTable.getMatchedFilters(interest, matchedFilters) for i in range(len(matchedFilters)): entry = matchedFilters[i] includeFilter = True onInterestCall = entry.getOnInterest() # If onInterest is not a function nor a method assumes it is a # calleable object if (not inspect.isfunction(onInterestCall) and not inspect.ismethod(onInterestCall)): onInterestCall = onInterestCall.__call__ # Use getcallargs to test if onInterest accepts 5 args. try: inspect.getcallargs(onInterestCall, None, None, None, None, None) except TypeError: # Assume onInterest is old-style with 4 arguments. includeFilter = False if includeFilter: try: entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId(), entry.getFilter()) except: logging.exception("Error in onInterest") else: # Old-style onInterest without the filter argument. We # still pass a Face instead of Transport since Face also # has a send method. try: entry.getOnInterest()( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId()) except: logging.exception("Error in onInterest") elif data != None: pendingInterests = [] self._pendingInterestTable.extractEntriesForExpressedInterest( data, pendingInterests) for pendingInterest in pendingInterests: try: pendingInterest.getOnData()(pendingInterest.getInterest(), data) except: logging.exception("Error in onData")