Ejemplo n.º 1
0
class Sha256WithRsaSignature(Signature):
    """
    Create a new Sha256WithRsaSignature object, possibly copying values from
    another object.

    :param value: (optional) If value is a Sha256WithRsaSignature, copy its
      values.  If value is omitted, the keyLocator is the default with
      unspecified values and the signature is unspecified.
    :param value: Sha256WithRsaSignature
    """
    def __init__(self, value = None):
        if value == None:
            self._keyLocator = ChangeCounter(KeyLocator())
            self._signature = Blob()
        elif type(value) is Sha256WithRsaSignature:
            # Copy its values.
            self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator()))
            self._signature = value._signature
        else:
            raise RuntimeError(
              "Unrecognized type for Sha256WithRsaSignature constructor: " +
              str(type(value)))

        self._changeCount = 0

    def clone(self):
        """
        Create a new Sha256WithRsaSignature which is a copy of this object.

        :return: A new object which is a copy of this object.
        :rtype: Sha256WithRsaSignature
        """
        return Sha256WithRsaSignature(self)

    def getKeyLocator(self):
        """
        Get the key locator.

        :return: The key locator.
        :rtype: KeyLocator
        """
        return self._keyLocator.get()

    def getSignature(self):
        """
        Get the data packet's signature bytes.

        :return: The signature bytes as a Blob, which maybe isNull().
        :rtype: Blob
        """
        return self._signature

    def setKeyLocator(self, keyLocator):
        """
        Set the key locator to a copy of the given keyLocator.

        :param KeyLocator keyLocator: The KeyLocator to copy.
        """
        self._keyLocator.set(KeyLocator(keyLocator))
        self._changeCount += 1

    def setSignature(self, signature):
        """
        Set the signature bytes to the given value.

        :param signature: The array with the signature bytes. If signature is
          not a Blob, then create a new Blob to copy the bytes (otherwise
          take another pointer to the same Blob).
        :type signature: A Blob or an array type with int elements
        """
        self._signature = (signature if type(signature) is Blob
                           else Blob(signature))
        self._changeCount += 1

    def clear(self):
        self._keyLocator.get().clear()
        self._signature = Blob()
        self._changeCount += 1

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._keyLocator.checkChanged()
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    keyLocator = property(getKeyLocator, setKeyLocator)
    signature = property(getSignature, setSignature)
Ejemplo n.º 2
0
class KeyLocator(object):
    """
    Create a new KeyLocator object, possibly copying values from
    another object.

    :param KeyLocator value: (optional) If value is a KeyLocator, copy its
      values.  If value is omitted, set the fields to unspecified.
    """
    def __init__(self, value = None):
        if value == None:
            self._type = None
            self._keyName = ChangeCounter(Name())
            self._keyData = Blob()
        elif isinstance(value, KeyLocator):
            # Copy its values.
            self._type = value._type
            self._keyName = ChangeCounter(Name(value.getKeyName()))
            self._keyData = value._keyData
        else:
            raise RuntimeError(
              "Unrecognized type for KeyLocator constructor: " +
              str(type(value)))

        self._changeCount = 0

    def getType(self):
        """
        Get the key locator type. If KeyLocatorType.KEYNAME, you may also
        getKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you may also
        getKeyData() to get the digest.

        :return: The key locator type, or None if not specified.
        :rtype: an int from KeyLocatorType
        """
        return self._type

    def getKeyName(self):
        """
        Get the key name.  This is meaningful if getType() is
        KeyLocatorType.KEYNAME.

        :return: The key name. If not specified, the Name is empty.
        :rtype: Name
        """
        return self._keyName.get()

    def getKeyData(self):
        """
        Get the key data.  This is the digest bytes if getType() is
        KeyLocatorType.KEY_LOCATOR_DIGEST.

        :return: The key data as a Blob, which isNull() if unspecified.
        :rtype: Blob
        """
        return self._keyData

    def setType(self, type):
        """
        Set the key locator type.  If KeyLocatorType.KEYNAME, you must also
        setKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you must also
        setKeyData() to set the digest.

        :param type: The key locator type.  If None, the type is unspecified.
        :type type: an int from KeyLocatorType
        """
        self._type = None if type == None or type < 0 else type
        self._changeCount += 1

    def setKeyName(self, keyName):
        """
        Set key name to a copy of the given Name.  This is the name if
        getType() is KeyLocatorType.KEYNAME.

        :param Name keyName: The key name which is copied.
        """
        self._keyName.set(keyName if isinstance(keyName, Name) else Name(keyName))
        self._changeCount += 1

    def setKeyData(self, keyData):
        """
        Set the key data to the given value.  This is the digest bytes if
        getType() is KeyLocatorType.KEY_LOCATOR_DIGEST.

        :param keyData: The array with the key data bytes. If keyData is not a
          Blob, then create a new Blob to copy the bytes (otherwise
          take another pointer to the same Blob).
        :type keyData: A Blob or an array type with int elements
        """
        self._keyData = keyData if isinstance(keyData, Blob) else Blob(keyData)
        self._changeCount += 1

    def clear(self):
        """
        Clear the fields and set the type to None.
        """
        self._type = None
        self._keyName.get().clear()
        self._keyData = Blob()
        self._changeCount += 1

    @staticmethod
    def canGetFromSignature(signature):
        """
        If the signature is a type that has a KeyLocator (so that
        getFromSignature will succeed), return true.
        Note: This is a static method of KeyLocator instead of a method of
        Signature so that the Signature base class does not need to be overloaded
        with all the different kinds of information that various signature
        algorithms may use.

        :param Signature signature: An object of a subclass of Signature.
        :return: True if the signature is a type that has a KeyLocator,
          otherwise False.
        :rtype: bool
        """
        return (isinstance(signature, Sha256WithEcdsaSignature) or
                isinstance(signature, Sha256WithRsaSignature) or
                isinstance(signature, HmacWithSha256Signature))

    @staticmethod
    def getFromSignature(signature):
        """
        If the signature is a type that has a KeyLocator, then return it. Otherwise
        throw an error.

        :param Signature signature: An object of a subclass of Signature.
        :return: The signature's KeyLocator. It is an error if signature doesn't
          have a KeyLocator.
        :rtype: KeyLocator
        """
        if (isinstance(signature, Sha256WithEcdsaSignature) or
            isinstance(signature, Sha256WithRsaSignature) or
            isinstance(signature, HmacWithSha256Signature)):
            return signature.getKeyLocator()
        else:
            raise RuntimeError(
              "KeyLocator.getFromSignature: Signature type does not have a KeyLocator")

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._keyName.checkChanged()
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    type = property(getType, setType)
    keyName = property(getKeyName, setKeyName)
    keyData = property(getKeyData, setKeyData)

    # Support property-based equivalence check
    # TODO: Desired syntax?
    def equals(self, other):
        if self is None and other is None: return True
        if other is None: return False

        if self._type != other._type:
            return False

        if self._type == KeyLocatorType.KEYNAME:
            if not self.getKeyName().equals(other.getKeyName()):
                return False

        if self._type == KeyLocatorType.KEY_LOCATOR_DIGEST:
            if not self.getKeyData().equals(other.getKeyData()):
                return False

        return True

    # Python operators

    def __eq__(self, other):
        return isinstance(other, KeyLocator) and self.equals(other)

    def __ne__(self, other):
        return not self == other
class Sha256WithIbsWatersSignature(Signature):
    """
    Create a new Sha256WithIbsWatersSignature object, possibly copying values from
    another object.

    :param value: (optional) If value is a Sha256WithIbsWatersSignature, copy its
      values.  If value is omitted, the keyLocator is the default with
      unspecified values and the signature is unspecified.
    :param value: Sha256WithIbsWatersSignature
    """
    def __init__(self, value=None):

        if value == None:
            self._keyLocator = ChangeCounter(KeyLocator())
            self._signature = Blob()
        elif type(value) is Sha256WithIbsWatersSignature:
            # Copy its values.
            self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator()))
            self._signature = value._signature
        else:
            raise RuntimeError(
                "Unrecognized type for Sha256WithIbsWatersSignature constructor: "
                + str(type(value)))

        self._changeCount = 0

    # signature methods:

    def clone(self):
        """
        Create a new Sha256WithIbsWatersSignature which is a copy of this signature.

        :return: A new object which is a copy of this object.
        :rtype: Sha256WithIbsWatersSignature
        """
        return Sha256WithIbsWatersSignature(self)

    def getSignature(self):
        """
        Get the data packet's signature bytes.

        :return: The signature bytes as a Blob, which maybe isNull().
        :rtype: Blob
        """
        return self._signature

    def setSignature(self, signature):
        """
        Set the signature bytes to the given value.

        :param signature: The array with the signature bytes. If signature is
          not a Blob, then create a new Blob to copy the bytes (otherwise
          take another pointer to the same Blob).
        :type signature: A Blob or an array type with int elements
        """
        self._signature = (signature
                           if type(signature) is Blob else Blob(signature))
        self._changeCount += 1

    def getKeyLocator(self):
        """
        Get the key locator.

        :return: The key locator.
        :rtype: KeyLocator
        """
        return self._keyLocator.get()

    def setKeyLocator(self, keyLocator):
        """
        Set the key locator to a copy of the given keyLocator.

        :param KeyLocator keyLocator: The KeyLocator to copy.
        """
        self._keyLocator.set(KeyLocator(keyLocator))
        self._changeCount += 1

    def clear(self):
        self._keyLocator.get().clear()
        self._signature = Blob()
        self._changeCount += 1

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._keyLocator.checkChanged()
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    keyLocator = property(getKeyLocator, setKeyLocator)
    signature = property(getSignature, setSignature)
Ejemplo n.º 4
0
Archivo: data.py Proyecto: MAHIS/PyNDN2
class Data(object):
    def __init__(self, value = None):
        if isinstance(value, Data):
            # Copy the values.
            self._name = ChangeCounter(Name(value.getName()))
            self._metaInfo = ChangeCounter(MetaInfo(value.getMetaInfo()))
            self._signature = ChangeCounter(value.getSignature().clone())
            self._content = value._content
            self._defaultWireEncoding = value.getDefaultWireEncoding()
            self._defaultWireEncodingFormat = value._defaultWireEncodingFormat
        else:
            self._name = ChangeCounter(Name(value) if type(value) is Name
                                                   else Name())
            self._metaInfo = ChangeCounter(MetaInfo())
            self._signature = ChangeCounter(Sha256WithRsaSignature())
            self._content = Blob()
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None

        self._getDefaultWireEncodingChangeCount = 0
        self._changeCount = 0

    def wireEncode(self, wireFormat = None):
        """
        Encode this Data for a particular wire format. If wireFormat is the
        default wire format, also set the defaultWireEncoding field to the
        encoded result.

        :param wireFormat: (optional) A WireFormat object used to encode this
           Data object. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The encoded buffer in a SignedBlob object.
        :rtype: SignedBlob
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if (not self.getDefaultWireEncoding().isNull() and
            self.getDefaultWireEncodingFormat() == wireFormat):
            # We already have an encoding in the desired format.
            return self.getDefaultWireEncoding()

        (encoding, signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.encodeData(self)
        wireEncoding = SignedBlob(
          encoding, signedPortionBeginOffset, signedPortionEndOffset)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.
            self._setDefaultWireEncoding(
              wireEncoding, WireFormat.getDefaultWireFormat())
        return wireEncoding

    def wireDecode(self, input, wireFormat = None):
        """
        Decode the input using a particular wire format and update this Data.
        If wireFormat is the default wire format, also set the
        defaultWireEncoding to another pointer to the input.

        :param input: The array with the bytes to decode. If input is not a
          Blob, then copy the bytes to save the defaultWireEncoding (otherwise
          take another pointer to the same Blob).
        :type input: A Blob or an array type with int elements
        :param wireFormat: (optional) A WireFormat object used to decode this
           Data object. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        # If input is a blob, get its buf().
        decodeBuffer = input.buf() if isinstance(input, Blob) else input
        (signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.decodeData(self, decodeBuffer)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.  In the Blob constructor, set
            #   copy true, but if input is already a Blob, it won't copy.
            self._setDefaultWireEncoding(SignedBlob(
                Blob(input, True),
                signedPortionBeginOffset, signedPortionEndOffset),
            WireFormat.getDefaultWireFormat())
        else:
            self._setDefaultWireEncoding(SignedBlob(), None)

    def getName(self):
        """
        Get the data packet's name.

        :return: The name.
        :rtype: Name
        """
        return self._name.get()

    def getMetaInfo(self):
        """
        Get the data packet's meta info.

        :return: The meta info.
        :rtype: MetaInfo
        """
        return self._metaInfo.get()

    def getSignature(self):
        """
        Get the data packet's signature object.

        :return: The signature object.
        :rtype: a subclass of Signature such as Sha256WithRsaSignature
        """
        return self._signature.get()

    def getContent(self):
        """
        Get the data packet's content.

        :return: The content as a Blob, which isNull() if unspecified.
        :rtype: Blob
        """
        return self._content

    def getDefaultWireEncoding(self):
        """
        Return the default wire encoding, which was encoded with
        getDefaultWireEncodingFormat().

        :return: The default wire encoding, whose isNull() may be true if there
          is no default wire encoding.
        :rtype: SignedBlob
        """
        if self._getDefaultWireEncodingChangeCount != self.getChangeCount():
            # The values have changed, so the default wire encoding is
            # invalidated.
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None
            self._getDefaultWireEncodingChangeCount = self.getChangeCount()

        return self._defaultWireEncoding

    def getDefaultWireEncodingFormat(self):
        """
        Get the WireFormat which is used by getDefaultWireEncoding().

        :return: The WireFormat, which is only meaningful if the
          getDefaultWireEncoding() is not isNull().
        :rtype: WireFormat
        """
        return self._defaultWireEncodingFormat

    def setName(self, name):
        """
        Set name to a copy of the given Name.

        :param Name name: The Name which is copied.
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._name.set(name if type(name) is Name else Name(name))
        self._changeCount += 1
        return self

    def setMetaInfo(self, metaInfo):
        """
        Set metaInfo to a copy of the given MetaInfo.

        :param MetaInfo metaInfo: The MetaInfo which is copied.
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._metaInfo.set(MetaInfo() if metaInfo == None
                                      else MetaInfo(metaInfo))
        self._changeCount += 1
        return self

    def setSignature(self, signature):
        """
        Set the signature to a copy of the given signature.

        :param signature: The signature object which is cloned.
        :type signature: a subclass of Signature such as Sha256WithRsaSignature
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._signature.set(Sha256WithRsaSignature() if signature == None
                                                     else signature.clone())
        self._changeCount += 1
        return self

    def setContent(self, content):
        """
        Set the content to the given value.

        :param content: The array with the content bytes. If content is not a
          Blob, then create a new Blob to copy the bytes (otherwise
          take another pointer to the same Blob).
        :type content: A Blob or an array type with int elements
        """
        self._content = content if type(content) is Blob else Blob(content)
        self._changeCount += 1

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._name.checkChanged()
        changed = self._metaInfo.checkChanged() or changed
        changed = self._signature.checkChanged() or changed
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    def _setDefaultWireEncoding(
          self, defaultWireEncoding, defaultWireEncodingFormat):
        self._defaultWireEncoding = defaultWireEncoding
        self._defaultWireEncodingFormat = defaultWireEncodingFormat
        # Set _getDefaultWireEncodingChangeCount so that the next call to
        # getDefaultWireEncoding() won't clear _defaultWireEncoding.
        self._getDefaultWireEncodingChangeCount = self.getChangeCount()

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    name = property(getName, setName)
    metaInfo = property(getMetaInfo, setMetaInfo)
    signature = property(getSignature, setSignature)
    content = property(getContent, setContent)
class Sha256WithAbsSignature(GenericSignature):

    def __init__(self, value = None):
        if value == None:
            self._keyLocator = ChangeCounter(KeyLocator())
            # self._validityPeriod = ChangeCounter(ValidityPeriod())
            self._signature = Blob()
        elif isinstance(value, Sha256WithAbsSignature):
            # Copy its values.
            self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator()))
            # self._validityPeriod = ChangeCounter(ValidityPeriod(value.getValidityPeriod()))
            self._signature = value._signature
        elif isinstance(value, GenericSignature):
            self.wireDecode(value.getSignatureInfoEncoding().toBuffer())
            self._signature = value.getSignature()
        else:
            raise RuntimeError(
              "Unrecognized type for Sha256WithAbsSignature constructor: " +
              str(type(value)))

        self._changeCount = 0

    def clone(self):
        """
        Create a new Sha256WithAbsSignature which is a copy of this object.

        :return: A new object which is a copy of this object.
        :rtype: Sha256WithAbsSignature
        """
        return Sha256WithAbsSignature(self)

    def getKeyLocator(self):
        """
        Get the key locator.

        :return: The key locator.
        :rtype: KeyLocator
        """
        return self._keyLocator.get()

    # def getValidityPeriod(self):
    #     """
    #     Get the validity period.

    #     :return: The validity period.
    #     :rtype: ValidityPeriod
    #     """
    #     return self._validityPeriod.get()

    def getSignature(self):
        """
        Get the data packet's signature bytes.

        :return: The signature bytes as a Blob, which maybe isNull().
        :rtype: Blob
        """
        return self._signature

    def setKeyLocator(self, keyLocator):
        """
        Set the key locator to a copy of the given keyLocator.

        :param KeyLocator keyLocator: The KeyLocator to copy.
        """
        self._keyLocator.set(KeyLocator(keyLocator))
        self._changeCount += 1

    # def setValidityPeriod(self, validityPeriod):
    #     """
    #     Set the validity period to a copy of the given ValidityPeriod.

    #     :param ValidityPeriod validityPeriod: The ValidityPeriod which is copied.
    #     """
    #     self._validityPeriod.set(ValidityPeriod(validityPeriod))
    #     self._changeCount += 1

    def setSignature(self, signature):
        """
        Set the signature bytes to the given value.

        :param signature: The array with the signature bytes. If signature is
          not a Blob, then create a new Blob to copy the bytes (otherwise
          take another pointer to the same Blob).
        :type signature: A Blob or an array type with int elements
        """
        self._signature = (signature if isinstance(signature, Blob)
                           else Blob(signature))
        self._changeCount += 1

    def clear(self):
        self._keyLocator.get().clear()
        self._signature = Blob()
        self._changeCount += 1

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._keyLocator.checkChanged()
        # changed = self._validityPeriod.checkChanged() or changed
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    def wireEncode(self):
        encoder = TlvEncoder(500)
        saveLength = len(encoder)
        
        # if self.getValidityPeriod().hasPeriod():
        #     Tlv0_2WireFormat._encodeValidityPeriod(self.getValidityPeriod(), encoder)
        Tlv0_2WireFormat._encodeKeyLocator(Tlv.KeyLocator, self.getKeyLocator(), encoder)
        encoder.writeNonNegativeIntegerTlv(Tlv.SignatureType, Tlv.SignatureType_Sha256WithAbsSignature)
        encoder.writeTypeAndLength(Tlv.SignatureInfo, len(encoder) - saveLength)

        self.setSignatureInfoEncoding(Blob(encoder.getOutput(), False), Tlv.SignatureType_Sha256WithAbsSignature)

    def wireDecode(self, wire):
        decoder = TlvDecoder(wire)

        beginOffset = decoder.getOffset()
        endOffset = decoder.readNestedTlvsStart(Tlv.SignatureInfo)

        signatureType = decoder.readNonNegativeIntegerTlv(Tlv.SignatureType)
        if signatureType != Tlv.SignatureType_Sha256WithAbsSignature:
            raise RuntimeError("Invalid SignatureType code: expected %d, got %d" % (Tlv.SignatureType_Sha256WithAbsSignature, signatureType))

        keyLocator = KeyLocator()
        Tlv0_2WireFormat._decodeKeyLocator(Tlv.KeyLocator, keyLocator, decoder, True)

        self._keyLocator = ChangeCounter(keyLocator)

        # if decoder.peekType(Tlv.ValidityPeriod_ValidityPeriod, endOffset):
        #     Tlv0_2WireFormat._decodeValidityPeriod(
        #         signatureInfo.getValidityPeriod(), decoder)

        decoder.finishNestedTlvs(endOffset)

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    keyLocator = property(getKeyLocator, setKeyLocator)
    signature = property(getSignature, setSignature)
Ejemplo n.º 6
0
class Data(object):
    def __init__(self, value=None):
        if isinstance(value, Data):
            # Copy the values.
            self._name = ChangeCounter(Name(value.getName()))
            self._metaInfo = ChangeCounter(MetaInfo(value.getMetaInfo()))
            self._signature = ChangeCounter(value.getSignature().clone())
            self._content = value._content
            self._defaultWireEncoding = value.getDefaultWireEncoding()
            self._defaultFullName = value._defaultFullName
            self._defaultWireEncodingFormat = value._defaultWireEncodingFormat
        else:
            self._name = ChangeCounter(
                Name(value) if type(value) is Name else Name())
            self._metaInfo = ChangeCounter(MetaInfo())
            self._signature = ChangeCounter(Sha256WithRsaSignature())
            self._content = Blob()
            self._defaultWireEncoding = SignedBlob()
            self._defaultFullName = Name()
            self._defaultWireEncodingFormat = None

        self._getDefaultWireEncodingChangeCount = 0
        self._changeCount = 0
        self._lpPacket = None

    def wireEncode(self, wireFormat=None):
        """
        Encode this Data for a particular wire format. If wireFormat is the
        default wire format, also set the defaultWireEncoding field to the
        encoded result.

        :param wireFormat: (optional) A WireFormat object used to encode this
           Data object. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The encoded buffer in a SignedBlob object.
        :rtype: SignedBlob
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if (not self.getDefaultWireEncoding().isNull()
                and self.getDefaultWireEncodingFormat() == wireFormat):
            # We already have an encoding in the desired format.
            return self.getDefaultWireEncoding()

        (encoding, signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.encodeData(self)
        wireEncoding = SignedBlob(encoding, signedPortionBeginOffset,
                                  signedPortionEndOffset)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.
            self._setDefaultWireEncoding(wireEncoding,
                                         WireFormat.getDefaultWireFormat())
        return wireEncoding

    def wireDecode(self, input, wireFormat=None):
        """
        Decode the input using a particular wire format and update this Data.
        If wireFormat is the default wire format, also set the
        defaultWireEncoding to another pointer to the input.

        :param input: The array with the bytes to decode. If input is not a
          Blob, then copy the bytes to save the defaultWireEncoding (otherwise
          take another pointer to the same Blob).
        :type input: A Blob or an array type with int elements
        :param wireFormat: (optional) A WireFormat object used to decode this
           Data object. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if isinstance(input, Blob):
            # Input is a blob, so get its buf() and set copy False.
            result = wireFormat.decodeData(self, input.buf(), False)
        else:
            result = wireFormat.decodeData(self, input, True)
        (signedPortionBeginOffset, signedPortionEndOffset) = result

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.  In the Blob constructor, set
            #   copy true, but if input is already a Blob, it won't copy.
            self._setDefaultWireEncoding(
                SignedBlob(Blob(input, True), signedPortionBeginOffset,
                           signedPortionEndOffset),
                WireFormat.getDefaultWireFormat())
        else:
            self._setDefaultWireEncoding(SignedBlob(), None)

    def getName(self):
        """
        Get the data packet's name.

        :return: The name.
        :rtype: Name
        """
        return self._name.get()

    def getMetaInfo(self):
        """
        Get the data packet's meta info.

        :return: The meta info.
        :rtype: MetaInfo
        """
        return self._metaInfo.get()

    def getSignature(self):
        """
        Get the data packet's signature object.

        :return: The signature object.
        :rtype: a subclass of Signature such as Sha256WithRsaSignature
        """
        return self._signature.get()

    def getContent(self):
        """
        Get the data packet's content.

        :return: The content as a Blob, which isNull() if unspecified.
        :rtype: Blob
        """
        return self._content

    def getDefaultWireEncoding(self):
        """
        Return the default wire encoding, which was encoded with
        getDefaultWireEncodingFormat().

        :return: The default wire encoding, whose isNull() may be true if there
          is no default wire encoding.
        :rtype: SignedBlob
        """
        if self._getDefaultWireEncodingChangeCount != self.getChangeCount():
            # The values have changed, so the default wire encoding is
            # invalidated.
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None
            self._getDefaultWireEncodingChangeCount = self.getChangeCount()

        return self._defaultWireEncoding

    def getDefaultWireEncodingFormat(self):
        """
        Get the WireFormat which is used by getDefaultWireEncoding().

        :return: The WireFormat, which is only meaningful if the
          getDefaultWireEncoding() is not isNull().
        :rtype: WireFormat
        """
        return self._defaultWireEncodingFormat

    def getIncomingFaceId(self):
        """
        Get the incoming face ID according to the incoming packet header.

        :return: The incoming face ID. If not specified, return None.
        :rtype: int
        """
        field = (None if self._lpPacket == None else
                 IncomingFaceId.getFirstHeader(self._lpPacket))
        return None if field == None else field.getFaceId()

    def getFullName(self, wireFormat=None):
        """
        Get the Data packet's full name, which includes the final
        ImplicitSha256Digest component based on the wire encoding for a
        particular wire format.

        :param wireFormat: (optional) A WireFormat object used to encode
           this object. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The full name. You must not change the Name object - if you
          need to change it then make a copy.
        :rtype: Name
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        # The default full name depends on the default wire encoding.
        if (not self.getDefaultWireEncoding().isNull()
                and self._defaultFullName.size() > 0
                and self.getDefaultWireEncodingFormat() == wireFormat):
            # We already have a full name. A non-null default wire encoding
            # means that the Data packet fields have not changed.
            return self._defaultFullName

        fullName = Name(self.getName())
        sha256 = hashes.Hash(hashes.SHA256(), backend=default_backend())
        sha256.update(self.wireEncode(wireFormat).toBytes())
        fullName.appendImplicitSha256Digest(
            Blob(bytearray(sha256.finalize()), False))

        if wireFormat == WireFormat.getDefaultWireFormat():
            # wireEncode has already set defaultWireEncodingFormat_.
            self._defaultFullName = fullName

        return fullName

    def setName(self, name):
        """
        Set name to a copy of the given Name.

        :param Name name: The Name which is copied.
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._name.set(name if type(name) is Name else Name(name))
        self._changeCount += 1
        return self

    def setMetaInfo(self, metaInfo):
        """
        Set metaInfo to a copy of the given MetaInfo.

        :param MetaInfo metaInfo: The MetaInfo which is copied.
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._metaInfo.set(MetaInfo() if metaInfo ==
                           None else MetaInfo(metaInfo))
        self._changeCount += 1
        return self

    def setSignature(self, signature):
        """
        Set the signature to a copy of the given signature.

        :param signature: The signature object which is cloned.
        :type signature: a subclass of Signature such as Sha256WithRsaSignature
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._signature.set(Sha256WithRsaSignature() if signature ==
                            None else signature.clone())
        self._changeCount += 1
        return self

    def setContent(self, content):
        """
        Set the content to the given value.

        :param content: The array with the content bytes. If content is not a
          Blob, then create a new Blob to copy the bytes (otherwise
          take another pointer to the same Blob).
        :type content: A Blob or an array type with int elements
        """
        self._content = content if isinstance(content, Blob) else Blob(content)
        self._changeCount += 1

    def setLpPacket(self, lpPacket):
        """
        An internal library method to set the LpPacket for an incoming packet.
        The application should not call this.

        :param LpPacket lpPacket: The LpPacket. This does not make a copy.
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        :note: This is an experimental feature. This API may change in the future.
        """
        self._lpPacket = lpPacket
        # Don't update _changeCount since this doesn't affect the wire encoding.
        return self

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._name.checkChanged()
        changed = self._metaInfo.checkChanged() or changed
        changed = self._signature.checkChanged() or changed
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    def _setDefaultWireEncoding(self, defaultWireEncoding,
                                defaultWireEncodingFormat):
        self._defaultWireEncoding = defaultWireEncoding
        self._defaultWireEncodingFormat = defaultWireEncodingFormat
        # Set _getDefaultWireEncodingChangeCount so that the next call to
        # getDefaultWireEncoding() won't clear _defaultWireEncoding.
        self._getDefaultWireEncodingChangeCount = self.getChangeCount()

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    name = property(getName, setName)
    metaInfo = property(getMetaInfo, setMetaInfo)
    signature = property(getSignature, setSignature)
    content = property(getContent, setContent)
Ejemplo n.º 7
0
class Interest(object):
    def __init__(self, value=None):
        if type(value) is Interest:
            # Copy the values.
            self._name = ChangeCounter(Name(value.getName()))
            self._minSuffixComponents = value._minSuffixComponents
            self._maxSuffixComponents = value._maxSuffixComponents
            self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator()))
            self._exclude = ChangeCounter(Exclude(value.getExclude()))
            self._childSelector = value._childSelector
            self._mustBeFresh = value._mustBeFresh

            self._nonce = value.getNonce()
            self._interestLifetimeMilliseconds = value._interestLifetimeMilliseconds
            self._forwardingHint = ChangeCounter(
                DelegationSet(value.getForwardingHint()))
            self._linkWireEncoding = value._linkWireEncoding
            self._linkWireEncodingFormat = value._linkWireEncodingFormat
            self._link = ChangeCounter(None)
            if value._link.get() != None:
                self._link.set(Link(value._link.get()))
            self._selectedDelegationIndex = value._selectedDelegationIndex
            self._defaultWireEncoding = value.getDefaultWireEncoding()
            self._defaultWireEncodingFormat = value._defaultWireEncodingFormat
            self._content = value._content
        else:
            self._name = ChangeCounter(
                Name(value) if type(value) is Name else Name())
            self._minSuffixComponents = None
            self._maxSuffixComponents = None
            self._keyLocator = ChangeCounter(KeyLocator())
            self._exclude = ChangeCounter(Exclude())
            self._childSelector = None
            self._mustBeFresh = True

            self._nonce = Blob()
            self._interestLifetimeMilliseconds = None
            self._forwardingHint = ChangeCounter(DelegationSet())
            self._linkWireEncoding = Blob()
            self._linkWireEncodingFormat = None
            self._link = ChangeCounter(None)
            self._selectedDelegationIndex = None
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None
            self._content = Blob()

        self._getNonceChangeCount = 0
        self._getDefaultWireEncodingChangeCount = 0
        self._changeCount = 0
        self._lpPacket = None

    def setContent(self, content):
        """
        Set the content to the given value.

        :param content: The array with the content bytes. If content is not a
          Blob, then create a new Blob to copy the bytes (otherwise
          take another pointer to the same Blob).
        :type content: A Blob or an array type with int elements
        """
        self._content = content if isinstance(content, Blob) else Blob(content)

    def getContent(self):
        """
        Get the data packet's content.

        :return: The content as a Blob, which isNull() if unspecified.
        :rtype: Blob
        """
        return self._content

    def getName(self):
        """
        Get the interest Name.

        :return: The name.  The name size() may be 0 if not specified.
        :rtype: Name
        """
        return self._name.get()

    def getMinSuffixComponents(self):
        """
        Get the min suffix components.

        :return: The min suffix components, or None if not specified.
        :rtype: int
        """
        return self._minSuffixComponents

    def getMaxSuffixComponents(self):
        """
        Get the max suffix components.

        :return: The max suffix components, or None if not specified.
        :rtype: int
        """
        return self._maxSuffixComponents

    def getKeyLocator(self):
        """
        Get the interest key locator.

        :return: The key locator. If getType() is None, then the key locator
          is not specified.
        :rtype: KeyLocator
        """
        return self._keyLocator.get()

    def getExclude(self):
        """
        Get the exclude object.

        :return: The exclude object. If the exclude size() is zero, then
          the exclude is not specified.
        :rtype: Exclude
        """
        return self._exclude.get()

    def getChildSelector(self):
        """
        Get the child selector.

        :return: The child selector, or None if not specified.
        :rtype: int
        """
        return self._childSelector

    def getMustBeFresh(self):
        """
        Get the must be fresh flag.

        :return: The must be fresh flag.  If not specified, the default is
          True.
        :rtype: bool
        """
        return self._mustBeFresh

    def getNonce(self):
        """
        Return the nonce value from the incoming interest.  If you change any of
        the fields in this Interest object, then the nonce value is cleared.

        :return: The nonce.  If isNull() then the nonce is omitted.
        :rtype: Blob
        """
        if self._getNonceChangeCount != self.getChangeCount():
            # The values have changed, so the existing nonce is invalidated.
            self._nonce = Blob()
            self._getNonceChangeCount = self.getChangeCount()

        return self._nonce

    def getForwardingHint(self):
        """
        Get the forwarding hint object which you can modify to add or remove
        forwarding hints.

        :return: The forwarding hint as a DelegationSet.
        :rtype: DelegationSet
        """
        return self._forwardingHint.get()

    def hasLink(self):
        """
        Check if this interest has a link object (or a link wire encoding which
        can be decoded to make the link object).

        :return:  True if this interest has a link object, False if not.
        :rtype: bool
        :deprecated: Use getForwardingHint.
        """
        return self._link.get() != None or not self._linkWireEncoding.isNull()

    def getLink(self):
        """
        Get the link object. If necessary, decode it from the link wire encoding.

        :return: The link object, or None if not specified.
        :rtype: Link
        :raises ValueError: For error decoding the link wire encoding (if
          necessary).
        :deprecated: Use getForwardingHint.
        """
        if self._link.get() != None:
            return self._link.get()
        elif not self._linkWireEncoding.isNull():
            # Decode the link object from linkWireEncoding_.
            link = Link()
            link.wireDecode(self._linkWireEncoding,
                            self._linkWireEncodingFormat)
            self._link.set(link)

            # Clear _linkWireEncoding since it is now managed by the link object.
            self._linkWireEncoding = Blob()
            self._linkWireEncodingFormat = None

            return link
        else:
            return None

    def getLinkWireEncoding(self, wireFormat=None):
        """
        Get the wire encoding of the link object. If there is already a wire
        encoding then return it. Otherwise encode from the link object (if
        available).

        :param WireFormat wireFormat: (optional) A WireFormat object used to
          encode the Link. If omitted, use WireFormat.getDefaultWireFormat().
        :return: The wire encoding, or an isNull Blob if the link is not
          specified.
        :rtype: Blob
        :deprecated: Use getForwardingHint.
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if (not self._linkWireEncoding.isNull()
                and self._linkWireEncodingFormat == wireFormat):
            return self._linkWireEncoding

        link = self.getLink()
        if link != None:
            return link.wireEncode(wireFormat)
        else:
            return Blob()

    def getSelectedDelegationIndex(self):
        """
        Get the selected delegation index.

        :return: The selected delegation index. If not specified, return None.
        :rtype: int
        :deprecated: Use getForwardingHint.
        """
        return self._selectedDelegationIndex

    def getInterestLifetimeMilliseconds(self):
        """
        Get the interest lifetime.

        :return: The interest lifetime in milliseconds, or None if not specified.
        :rtype: float
        """
        return self._interestLifetimeMilliseconds

    def getIncomingFaceId(self):
        """
        Get the incoming face ID according to the incoming packet header.

        :return: The incoming face ID. If not specified, return None.
        :rtype: int
        """
        field = (None if self._lpPacket == None else
                 IncomingFaceId.getFirstHeader(self._lpPacket))
        return None if field == None else field.getFaceId()

    def setName(self, name):
        """
        Set the interest name.

        :note: You can also call getName and change the name values directly.
        :param Name name: The interest name. This makes a copy of the name.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._name.set(name if type(name) is Name else Name(name))
        self._changeCount += 1
        return self

    def setMinSuffixComponents(self, minSuffixComponents):
        """
        Set the min suffix components count.

        :param int minSuffixComponents: The min suffix components count. If not
          specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._minSuffixComponents = Common.nonNegativeIntOrNone(
            minSuffixComponents)
        self._changeCount += 1
        return self

    def setMaxSuffixComponents(self, maxSuffixComponents):
        """
        Set the max suffix components count.

        :param int maxSuffixComponents: The max suffix components count. If not
          specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._maxSuffixComponents = Common.nonNegativeIntOrNone(
            maxSuffixComponents)
        self._changeCount += 1
        return self

    def setKeyLocator(self, keyLocator):
        """
        Set this interest to use a copy of the given KeyLocator object.

        :note: You can also call getKeyLocator and change the key locator directly.
        :param KeyLocator keyLocator: The KeyLocator object. This makes a copy
          of the object. If no key locator is specified, set to a new default
          KeyLocator(), or to a KeyLocator with an unspecified type.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._keyLocator.set(
            KeyLocator(keyLocator
                       ) if type(keyLocator) is KeyLocator else KeyLocator())
        self._changeCount += 1
        return self

    def setExclude(self, exclude):
        """
        Set this interest to use a copy of the given Exclude object.

        :note: You can also call getExclude and change the exclude entries directly.
        :param Exclude exclude: The Exclude object. This makes a copy of the
          object. If no exclude is specified, set to a new default Exclude(), or
          to an Exclude with size() 0.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._exclude.set(
            Exclude(exclude) if type(exclude) is Exclude else Exclude())
        self._changeCount += 1
        return self

    def setForwardingHint(self, forwardingHint):
        """
        Set this interest to use a copy of the given DelegationSet object as the
        forwarding hint.

        :note: You can also call getForwardingHint and change the forwarding
          hint directly.
        :param DelegationSet forwardingHint: The DelegationSet object to use as
          the forwarding  hint. This makes a copy of the object. If no
          forwarding hint is specified, set to a new default DelegationSet()
          with no entries.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._forwardingHint.set(
            DelegationSet(forwardingHint)
            if type(forwardingHint) is DelegationSet else DelegationSet())
        self._changeCount += 1
        return self

    def setLinkWireEncoding(self, encoding, wireFormat=None):
        """
        Set the link wire encoding bytes, without decoding them. If there is a
        link object, set it to None. If you later call getLink(), it will decode
        the wireEncoding to create the link object.

        :param Blob encoding: The Blob with the bytes of the link wire encoding.
          If no link is specified, set to an empty Blob() or call unsetLink().
        :param WireFormat wireFormat: The wire format of the encoding, to be
          used later if necessary to decode. If omitted, use
          WireFormat.getDefaultWireFormat().
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        :deprecated: Use setForwardingHint.
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        self._linkWireEncoding = encoding
        self._linkWireEncodingFormat = wireFormat

        # Clear the link object, assuming that it has a different encoding.
        self._link.set(None)

        self._changeCount += 1
        return self

    def unsetLink(self):
        """
        Clear the link wire encoding and link object so that getLink() returns
        None.

        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        :deprecated: Use setForwardingHint.
        """
        return self.setLinkWireEncoding(Blob(), None)

    def setSelectedDelegationIndex(self, selectedDelegationIndex):
        """
        Set the selected delegation index.

        :param int selectedDelegationIndex: The selected delegation index. If
          not specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        :deprecated: Use setForwardingHint.
        """
        self._selectedDelegationIndex = Common.nonNegativeIntOrNone(
            selectedDelegationIndex)
        self._changeCount += 1
        return self

    def setChildSelector(self, childSelector):
        """
        Set the child selector.

        :param int childSelector: The child selector. If not specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._childSelector = Common.nonNegativeIntOrNone(childSelector)
        self._changeCount += 1
        return self

    def setMustBeFresh(self, mustBeFresh):
        """
        Set the MustBeFresh flag.

        :param bool mustBeFresh: True if the content must be fresh, otherwise
          False. If you do not set this flag, the default value is true.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._mustBeFresh = True if mustBeFresh else False
        self._changeCount += 1
        return self

    def setNonce(self, nonce):
        """
        :deprecated: You should let the wire encoder generate a random nonce
          internally before sending the interest.
        """
        self._nonce = nonce if isinstance(nonce, Blob) else Blob(nonce)
        # Set _getNonceChangeCount so that the next call to getNonce() won't
        #   clear _nonce.
        self._changeCount += 1
        self._getNonceChangeCount = self.getChangeCount()
        return self

    def setInterestLifetimeMilliseconds(self, interestLifetimeMilliseconds):
        """
        Set the interest lifetime.

        :param float interestLifetimeMilliseconds: The interest lifetime in
          milliseconds. If not specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._interestLifetimeMilliseconds = Common.nonNegativeFloatOrNone(
            interestLifetimeMilliseconds)
        self._changeCount += 1
        return self

    def wireEncode(self, wireFormat=None):
        """
        Encode this Interest for a particular wire format. If wireFormat is the
        default wire format, also set the defaultWireEncoding field to the
        encoded result.

        :param wireFormat: (optional) A WireFormat object used to encode this
           Interest. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The encoded buffer.
        :rtype: SignedBlob
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if (not self.getDefaultWireEncoding().isNull()
                and self.getDefaultWireEncodingFormat() == wireFormat):
            # We already have an encoding in the desired format.
            return self.getDefaultWireEncoding()

        (encoding, signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.encodeInterest(self)
        wireEncoding = SignedBlob(encoding, signedPortionBeginOffset,
                                  signedPortionEndOffset)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.
            self._setDefaultWireEncoding(wireEncoding,
                                         WireFormat.getDefaultWireFormat())
        return wireEncoding

    def wireDecode(self, input, wireFormat=None):
        """
        Decode the input using a particular wire format and update this Interest.
        If wireFormat is the default wire format, also set the
        defaultWireEncoding to another pointer to the input.

        :param input: The array with the bytes to decode. If input is not a
          Blob, then copy the bytes to save the defaultWireEncoding (otherwise
          take another pointer to the same Blob).
        :type input: A Blob or an array type with int elements
        :param wireFormat: (optional) A WireFormat object used to decode this
           Interest. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if isinstance(input, Blob):
            # Input is a blob, so get its buf() and set copy False.
            result = wireFormat.decodeInterest(self, input.buf(), False)
        else:
            result = wireFormat.decodeInterest(self, input, True)
        (signedPortionBeginOffset, signedPortionEndOffset) = result

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.  In the Blob constructor, set
            #   copy true, but if input is already a Blob, it won't copy.
            self._setDefaultWireEncoding(
                SignedBlob(Blob(input, True), signedPortionBeginOffset,
                           signedPortionEndOffset),
                WireFormat.getDefaultWireFormat())
        else:
            self._setDefaultWireEncoding(SignedBlob(), None)

    def toUri(self):
        """
        Encode the name according to the "NDN URI Scheme".  If there are
        interest selectors, append "?" and add the selectors as a query string.
        For example "/test/name?ndn.ChildSelector=1".
        :note: This is an experimental feature. See the API docs for more detail at
        http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method .

        :return: The URI string.
        :rtype: string
        """
        selectors = ""
        if self._minSuffixComponents != None:
            selectors += "&ndn.MinSuffixComponents=" + repr(
                self._minSuffixComponents)
        if self._maxSuffixComponents != None:
            selectors += "&ndn.MaxSuffixComponents=" + repr(
                self._maxSuffixComponents)
        if self._childSelector != None:
            selectors += "&ndn.ChildSelector=" + repr(self._childSelector)
        if self._mustBeFresh:
            selectors += "&ndn.MustBeFresh=true"
        if self._interestLifetimeMilliseconds != None:
            selectors += "&ndn.InterestLifetime=" + repr(
                int(round(self._interestLifetimeMilliseconds)))
        if self.getNonce().size() > 0:
            selectors += ("&ndn.Nonce=" +
                          Name.toEscapedString(self.getNonce().buf()))
        if self.getExclude().size() > 0:
            selectors += "&ndn.Exclude=" + self.getExclude().toUri()

        result = self.getName().toUri()
        if selectors != "":
            # Replace the first & with ?.
            result += "?" + selectors[1:]

        return result

    def refreshNonce(self):
        """
        Update the bytes of the nonce with new random values. This ensures that
        the new nonce value is different than the current one. If the current
        nonce is not specified, this does nothing.
        """
        currentNonce = self.getNonce()
        if currentNonce.size() == 0:
            return

        while True:
            value = bytearray(currentNonce.size())
            for i in range(len(value)):
                value[i] = self._systemRandom.randint(0, 0xff)
            newNonce = Blob(value, False)
            if newNonce != currentNonce:
                break

        self._nonce = newNonce
        # Set _getNonceChangeCount so that the next call to getNonce() won't
        #   clear _nonce.
        self._changeCount += 1
        self._getNonceChangeCount = self.getChangeCount()

    def matchesName(self, name):
        """
        Check if this interest's name matches the given name (using Name.match)
        and the given name also conforms to the interest selectors.

        :param Name name: The name to check.
        :return: True if the name and interest selectors match, False otherwise.
        :rtype: bool
        """
        if not self.getName().match(name):
            return False

        if (self._minSuffixComponents != None and
                # Add 1 for the implicit digest.
                not (name.size() + 1 - self.getName().size() >=
                     self._minSuffixComponents)):
            return False
        if (self._maxSuffixComponents != None and
                # Add 1 for the implicit digest.
                not (name.size() + 1 - self.getName().size() <=
                     self._maxSuffixComponents)):
            return False
        if (self.getExclude().size() > 0
                and name.size() > self.getName().size()
                and self.getExclude().matches(name[self.getName().size()])):
            return False

        return True

    def matchesData(self, data, wireFormat=None):
        """
        Check if the given Data packet can satisfy this Interest. This method
        considers the Name, MinSuffixComponents, MaxSuffixComponents,
        PublisherPublicKeyLocator, and Exclude. It does not consider the
        ChildSelector or MustBeFresh. This uses the given wireFormat to get the
        Data packet encoding for the full Name.

        :param Data data: The Data packet to check.
        :param wireFormat: (optional) A WireFormat object used to encode the
          Data packet to get its full Name. If omitted, use
          WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: True if the given Data packet can satisfy this Interest.
        :rtype: bool
        """
        # Imitate ndn-cxx Interest::matchesData.
        interestNameLength = self.getName().size()
        dataName = data.getName()
        fullNameLength = dataName.size() + 1

        # Check MinSuffixComponents.
        hasMinSuffixComponents = (self.getMinSuffixComponents() != None)
        minSuffixComponents = (self.getMinSuffixComponents()
                               if hasMinSuffixComponents else 0)
        if not (interestNameLength + minSuffixComponents <= fullNameLength):
            return False

        # Check MaxSuffixComponents.
        hasMaxSuffixComponents = (self.getMaxSuffixComponents() != None)
        if (hasMaxSuffixComponents
                and not (interestNameLength + self.getMaxSuffixComponents() >=
                         fullNameLength)):
            return False

        # Check the prefix.
        if interestNameLength == fullNameLength:
            if self.getName().get(-1).isImplicitSha256Digest():
                if not self.getName().equals(data.getFullName(wireFormat)):
                    return False
            else:
                # The Interest Name is the same length as the Data full Name,
                #   but the last component isn't a digest so there's no
                #   possibility of matching.
                return False
        else:
            # The Interest Name should be a strict prefix of the Data full Name.
            if not self.getName().isPrefixOf(dataName):
                return False

        # Check the Exclude.
        # The Exclude won't be violated if the Interest Name is the same as the
        #   Data full Name.
        if self.getExclude().size(
        ) > 0 and fullNameLength > interestNameLength:
            if interestNameLength == fullNameLength - 1:
                # The component to exclude is the digest.
                if self.getExclude().matches(
                        data.getFullName(wireFormat).get(interestNameLength)):
                    return False
            else:
                # The component to exclude is not the digest.
                if self.getExclude().matches(dataName.get(interestNameLength)):
                    return False

        # Check the KeyLocator.
        publisherPublicKeyLocator = self.getKeyLocator()
        if publisherPublicKeyLocator.getType() != None:
            signature = data.getSignature()
            if not KeyLocator.canGetFromSignature(signature):
                # No KeyLocator in the Data packet.
                return False
            if not publisherPublicKeyLocator.equals(
                (KeyLocator.getFromSignature(signature))):
                return False

        return True

    def getDefaultWireEncoding(self):
        """
        Return the default wire encoding, which was encoded with
        getDefaultWireEncodingFormat().

        :return: The default wire encoding, whose isNull() may be true if there
          is no default wire encoding.
        :rtype: SignedBlob
        """
        if self._getDefaultWireEncodingChangeCount != self.getChangeCount():
            # The values have changed, so the default wire encoding is
            # invalidated.
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None
            self._getDefaultWireEncodingChangeCount = self.getChangeCount()

        return self._defaultWireEncoding

    def getDefaultWireEncodingFormat(self):
        """
        Get the WireFormat which is used by getDefaultWireEncoding().

        :return: The WireFormat, which is only meaningful if the
          getDefaultWireEncoding() is not isNull().
        :rtype: WireFormat
        """
        return self._defaultWireEncodingFormat

    def setLpPacket(self, lpPacket):
        """
        An internal library method to set the LpPacket for an incoming packet.
        The application should not call this.

        :param LpPacket lpPacket: The LpPacket. This does not make a copy.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        :note: This is an experimental feature. This API may change in the future.
        """
        self._lpPacket = lpPacket
        # Don't update _changeCount since this doesn't affect the wire encoding.
        return self

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._name.checkChanged()
        changed = self._keyLocator.checkChanged() or changed
        changed = self._exclude.checkChanged() or changed
        changed = self._forwardingHint.checkChanged() or changed
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    def _setDefaultWireEncoding(self, defaultWireEncoding,
                                defaultWireEncodingFormat):
        self._defaultWireEncoding = defaultWireEncoding
        self._defaultWireEncodingFormat = defaultWireEncodingFormat
        # Set _getDefaultWireEncodingChangeCount so that the next call to
        # getDefaultWireEncoding() won't clear _defaultWireEncoding.
        self._getDefaultWireEncodingChangeCount = self.getChangeCount()

    _systemRandom = SystemRandom()

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    name = property(getName, setName)
    minSuffixComponents = property(getMinSuffixComponents,
                                   setMinSuffixComponents)
    maxSuffixComponents = property(getMaxSuffixComponents,
                                   setMaxSuffixComponents)
    keyLocator = property(getKeyLocator, setKeyLocator)
    exclude = property(getExclude, setExclude)
    childSelector = property(getChildSelector, setChildSelector)
    mustBeFresh = property(getMustBeFresh, setMustBeFresh)
    nonce = property(getNonce, setNonce)
    interestLifetimeMilliseconds = property(getInterestLifetimeMilliseconds,
                                            setInterestLifetimeMilliseconds)
    content = property(getContent, setContent)
Ejemplo n.º 8
0
class KeyLocator(object):
    """
    Create a new KeyLocator object, possibly copying values from
    another object.

    :param KeyLocator value: (optional) If value is a KeyLocator, copy its
      values.  If value is omitted, set the fields to unspecified.
    """
    def __init__(self, value = None):
        if value == None:
            self._type = None
            self._keyName = ChangeCounter(Name())
            self._keyData = Blob()
        elif type(value) is KeyLocator:
            # Copy its values.
            self._type = value._type
            self._keyName = ChangeCounter(Name(value.getKeyName()))
            self._keyData = value._keyData
        else:
            raise RuntimeError(
              "Unrecognized type for KeyLocator constructor: " +
              repr(type(value)))

        self._changeCount = 0

    def getType(self):
        """
        Get the key locator type. If KeyLocatorType.KEYNAME, you may also
        getKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you may also
        getKeyData() to get the digest.

        :return: The key locator type, or None if not specified.
        :rtype: an int from KeyLocatorType
        """
        return self._type

    def getKeyName(self):
        """
        Get the key name.  This is meaningful if getType() is
        KeyLocatorType.KEYNAME.

        :return: The key name. If not specified, the Name is empty.
        :rtype: Name
        """
        return self._keyName.get()

    def getKeyData(self):
        """
        Get the key data.  This is the digest bytes if getType() is
        KeyLocatorType.KEY_LOCATOR_DIGEST.

        :return: The key data as a Blob, which isNull() if unspecified.
        :rtype: Blob
        """
        return self._keyData

    def setType(self, type):
        """
        Set the key locator type.  If KeyLocatorType.KEYNAME, you must also
        setKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you must also
        setKeyData() to the digest.

        :param type: The key locator type.  If None, the type is unspecified.
        :type type: an int from KeyLocatorType
        """
        self._type = None if type == None or type < 0 else type
        self._changeCount += 1

    def setKeyName(self, keyName):
        """
        Set key name to a copy of the given Name.  This is the name if
        getType() is KeyLocatorType.KEYNAME.

        :param Name keyName: The key name which is copied.
        """
        self._keyName.set(keyName if type(keyName) is Name else Name(keyName))
        self._changeCount += 1

    def setKeyData(self, keyData):
        """
        Set the key data to the given value.  This is the digest bytes if
        getType() is KeyLocatorType.KEY_LOCATOR_DIGEST.

        :param keyData: The array with the key data bytes. If keyData is not a
          Blob, then create a new Blob to copy the bytes (otherwise
          take another pointer to the same Blob).
        :type keyData: A Blob or an array type with int elements
        """
        self._keyData = keyData if type(keyData) is Blob else Blob(keyData)
        self._changeCount += 1

    def clear(self):
        """
        Clear the fields and set the type to None.
        """
        self._type = None
        self._keyName.get().clear()
        self._keyData = Blob()
        self._changeCount += 1

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._keyName.checkChanged()
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount
Ejemplo n.º 9
0
class Interest(object):
    def __init__(self, value=None):
        if type(value) is Interest:
            # Copy the values.
            self._name = ChangeCounter(Name(value.getName()))
            self._minSuffixComponents = value._minSuffixComponents
            self._maxSuffixComponents = value._maxSuffixComponents
            self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator()))
            self._exclude = ChangeCounter(Exclude(value.getExclude()))
            self._childSelector = value._childSelector
            self._mustBeFresh = value._mustBeFresh

            self._nonce = value.getNonce()
            self._scope = value._scope
            self._interestLifetimeMilliseconds = value._interestLifetimeMilliseconds
        else:
            self._name = ChangeCounter(
                Name(value) if type(value) is Name else Name())
            self._minSuffixComponents = None
            self._maxSuffixComponents = None
            self._keyLocator = ChangeCounter(KeyLocator())
            self._exclude = ChangeCounter(Exclude())
            self._childSelector = None
            self._mustBeFresh = True

            self._nonce = Blob()
            self._scope = None
            self._interestLifetimeMilliseconds = None

        self._getNonceChangeCount = 0
        self._changeCount = 0

    def getName(self):
        """
        Get the interest Name.
        
        :return: The name.  The name size() may be 0 if not specified.
        :rtype: Name
        """
        return self._name.get()

    def getMinSuffixComponents(self):
        """
        Get the min suffix components.
        
        :return: The min suffix components, or None if not specified.
        :rtype: int
        """
        return self._minSuffixComponents

    def getMaxSuffixComponents(self):
        """
        Get the max suffix components.
        
        :return: The max suffix components, or None if not specified.
        :rtype: int
        """
        return self._maxSuffixComponents

    def getKeyLocator(self):
        """
        Get the interest key locator.
        
        :return: The key locator. If getType() is None, then the key locator
          is not specified.
        :rtype: KeyLocator
        """
        return self._keyLocator.get()

    def getExclude(self):
        """
        Get the exclude object.
        
        :return: The exclude object. If the exclude size() is zero, then
          the exclude is not specified.
        :rtype: Exclude
        """
        return self._exclude.get()

    def getChildSelector(self):
        """
        Get the child selector.
        
        :return: The child selector, or None if not specified.
        :rtype: int
        """
        return self._childSelector

    def getMustBeFresh(self):
        """
        Get the must be fresh flag.
        
        :return: The must be fresh flag.  If not specified, the default is 
          True.
        :rtype: bool
        """
        return self._mustBeFresh

    def getNonce(self):
        """
        Return the nonce value from the incoming interest.  If you change any of
        the fields in this Interest object, then the nonce value is cleared.
        
        :return: The nonce.  If isNull() then the nonce is omitted.
        :rtype: Blob
        """
        if self._getNonceChangeCount != self.getChangeCount():
            # The values have changed, so the existing nonce is invalidated.
            self._nonce = Blob()
            self._getNonceChangeCount = self.getChangeCount()

        return self._nonce

    def getScope(self):
        """
        Get the interest scope.
        
        :return: The scope, or None if not specified.
        :rtype: int
        """
        return self._scope

    def getInterestLifetimeMilliseconds(self):
        """
        Get the interest lifetime.
        
        :return: The interest lifetime in milliseconds, or None if not specified.
        :rtype: float
        """
        return self._interestLifetimeMilliseconds

    def setName(self, name):
        self._name.set(name if type(name) is Name else Name(name))
        self._changeCount += 1

    def setMinSuffixComponents(self, minSuffixComponents):
        self._minSuffixComponents = minSuffixComponents
        self._changeCount += 1

    def setMaxSuffixComponents(self, maxSuffixComponents):
        self._maxSuffixComponents = maxSuffixComponents
        self._changeCount += 1

    def setKeyLocator(self, keyLocator):
        """
        Set this interest to use a copy of the given keyLocator.
        Note: You can also change this interest's key locator modifying
        the object from getKeyLocator().
        
        :param KeyLocator keyLocator: The KeyLocator that is copied.
        """
        self._keyLocator.set(keyLocator if type(keyLocator) is KeyLocator(
            keyLocator) else KeyLocator())
        self._changeCount += 1

    def setExclude(self, exclude):
        """
        Set this interest to use a copy of the given exclude object.
        Note: You can also change this interest's exclude object modifying
        the object from getExclude().
        
        :param Exclude exclude: The exlcude object that is copied.
        """
        self._exclude.set(
            Exclude(exclude) if type(exclude) is Exclude else Exclude())
        self._changeCount += 1

    def setChildSelector(self, childSelector):
        self._childSelector = childSelector
        self._changeCount += 1

    def setMustBeFresh(self, mustBeFresh):
        self._mustBeFresh = True if mustBeFresh else False
        self._changeCount += 1

    def setNonce(self, nonce):
        self._nonce = nonce if type(nonce) is Blob else Blob(nonce)
        # Set _getNonceChangeCount so that the next call to getNonce() won't
        #   clear _nonce.
        self._changeCount += 1
        self._getNonceChangeCount = self.getChangeCount()

    def setScope(self, scope):
        self._scope = scope
        self._changeCount += 1

    def setInterestLifetimeMilliseconds(self, interestLifetimeMilliseconds):
        self._interestLifetimeMilliseconds = (
            None if interestLifetimeMilliseconds == None else
            float(interestLifetimeMilliseconds))
        self._changeCount += 1

    def wireEncode(self, wireFormat=None):
        """
        Encode this Interest for a particular wire format.
        
        :param wireFormat: (optional) A WireFormat object used to encode this 
           Interest. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The encoded buffer.
        :rtype: Blob
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        (encoding, signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.encodeInterest(self)
        return SignedBlob(encoding, signedPortionBeginOffset,
                          signedPortionEndOffset)

    def wireDecode(self, input, wireFormat=None):
        """
        Decode the input using a particular wire format and update this Interest.
        
        :param input: The array with the bytes to decode.
        :type input: An array type with int elements
        :param wireFormat: (optional) A WireFormat object used to decode this 
           Interest. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        # If input is a blob, get its buf().
        decodeBuffer = input.buf() if isinstance(input, Blob) else input
        wireFormat.decodeInterest(self, decodeBuffer)

    def toUri(self):
        """
        Encode the name according to the "NDN URI Scheme".  If there are 
        interest selectors, append "?" and add the selectors as a query string.  
        For example "/test/name?ndn.ChildSelector=1".
        :note: This is an experimental feature. See the API docs for more detail at 
        http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method .
        
        :return: The URI string.
        :rtype: string
        """
        selectors = ""
        if self._minSuffixComponents != None:
            selectors += "&ndn.MinSuffixComponents=" + repr(
                self._minSuffixComponents)
        if self._maxSuffixComponents != None:
            selectors += "&ndn.MaxSuffixComponents=" + repr(
                self._maxSuffixComponents)
        if self._childSelector != None:
            selectors += "&ndn.ChildSelector=" + repr(self._childSelector)
        if self._mustBeFresh:
            selectors += "&ndn.MustBeFresh=true"
        if self._scope != None:
            selectors += "&ndn.Scope=" + repr(self._scope)
        if self._interestLifetimeMilliseconds != None:
            selectors += "&ndn.InterestLifetime=" + repr(
                int(round(self._interestLifetimeMilliseconds)))
        if self.getNonce().size() > 0:
            selectors += ("&ndn.Nonce=" +
                          Name.toEscapedString(self.getNonce().buf()))
        if self.getExclude().size() > 0:
            selectors += "&ndn.Exclude=" + self.getExclude().toUri()

        result = self.getName().toUri()
        if selectors != "":
            # Replace the first & with ?.
            result += "?" + selectors[1:]

        return result

    def matchesName(self, name):
        """
        Check if this interest's name matches the given name (using Name.match) 
        and the given name also conforms to the interest selectors.
        
        :param Name name: The name to check.
        :return: True if the name and interest selectors match, False otherwise.
        :rtype: bool
        """
        if not self.getName().match(name):
            return False

        if (self._minSuffixComponents != None and
                # Add 1 for the implicit digest.
                not (name.size() + 1 - self.getName().size() >=
                     self._minSuffixComponents)):
            return False
        if (self._maxSuffixComponents != None and
                # Add 1 for the implicit digest.
                not (name.size() + 1 - self.getName().size() <=
                     self._maxSuffixComponents)):
            return False
        if (self.getExclude().size() > 0
                and name.size() > self.getName().size()
                and self.getExclude().matches(name[self.getName().size()])):
            return False

        return True

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object 
        (or a child object) is changed.
        
        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._name.checkChanged()
        changed = self._keyLocator.checkChanged() or changed
        changed = self._exclude.checkChanged() or changed
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount
Ejemplo n.º 10
0
class Interest(object):
    def __init__(self, value=None):
        if type(value) is Interest:
            # Copy the values.
            self._name = ChangeCounter(Name(value.getName()))
            self._minSuffixComponents = value._minSuffixComponents
            self._maxSuffixComponents = value._maxSuffixComponents
            self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator()))
            self._exclude = ChangeCounter(Exclude(value.getExclude()))
            self._childSelector = value._childSelector
            self._mustBeFresh = value._mustBeFresh

            self._nonce = value.getNonce()
            self._scope = value._scope
            self._interestLifetimeMilliseconds = value._interestLifetimeMilliseconds
            self._defaultWireEncoding = value.getDefaultWireEncoding()
            self._defaultWireEncodingFormat = value._defaultWireEncodingFormat
        else:
            self._name = ChangeCounter(
                Name(value) if type(value) is Name else Name())
            self._minSuffixComponents = None
            self._maxSuffixComponents = None
            self._keyLocator = ChangeCounter(KeyLocator())
            self._exclude = ChangeCounter(Exclude())
            self._childSelector = None
            self._mustBeFresh = True

            self._nonce = Blob()
            self._scope = None
            self._interestLifetimeMilliseconds = None
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None

        self._getNonceChangeCount = 0
        self._getDefaultWireEncodingChangeCount = 0
        self._changeCount = 0

    def getName(self):
        """
        Get the interest Name.

        :return: The name.  The name size() may be 0 if not specified.
        :rtype: Name
        """
        return self._name.get()

    def getMinSuffixComponents(self):
        """
        Get the min suffix components.

        :return: The min suffix components, or None if not specified.
        :rtype: int
        """
        return self._minSuffixComponents

    def getMaxSuffixComponents(self):
        """
        Get the max suffix components.

        :return: The max suffix components, or None if not specified.
        :rtype: int
        """
        return self._maxSuffixComponents

    def getKeyLocator(self):
        """
        Get the interest key locator.

        :return: The key locator. If getType() is None, then the key locator
          is not specified.
        :rtype: KeyLocator
        """
        return self._keyLocator.get()

    def getExclude(self):
        """
        Get the exclude object.

        :return: The exclude object. If the exclude size() is zero, then
          the exclude is not specified.
        :rtype: Exclude
        """
        return self._exclude.get()

    def getChildSelector(self):
        """
        Get the child selector.

        :return: The child selector, or None if not specified.
        :rtype: int
        """
        return self._childSelector

    def getMustBeFresh(self):
        """
        Get the must be fresh flag.

        :return: The must be fresh flag.  If not specified, the default is
          True.
        :rtype: bool
        """
        return self._mustBeFresh

    def getNonce(self):
        """
        Return the nonce value from the incoming interest.  If you change any of
        the fields in this Interest object, then the nonce value is cleared.

        :return: The nonce.  If isNull() then the nonce is omitted.
        :rtype: Blob
        """
        if self._getNonceChangeCount != self.getChangeCount():
            # The values have changed, so the existing nonce is invalidated.
            self._nonce = Blob()
            self._getNonceChangeCount = self.getChangeCount()

        return self._nonce

    def getScope(self):
        """
        :deprecated: Scope is not used by NFD.
        """
        if not WireFormat.ENABLE_NDNX:
            raise RuntimeError(
                "getScope is for NDNx and is deprecated. To enable while you upgrade your code to not use Scope, set WireFormat.ENABLE_NDNX = True"
            )

        return self._scope

    def getInterestLifetimeMilliseconds(self):
        """
        Get the interest lifetime.

        :return: The interest lifetime in milliseconds, or None if not specified.
        :rtype: float
        """
        return self._interestLifetimeMilliseconds

    def setName(self, name):
        """
        Set the interest name.

        :note: You can also call getName and change the name values directly.
        :param Name name: The interest name. This makes a copy of the name.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._name.set(name if type(name) is Name else Name(name))
        self._changeCount += 1
        return self

    def setMinSuffixComponents(self, minSuffixComponents):
        """
        Set the min suffix components count.

        :param int minSuffixComponents: The min suffix components count. If not
          specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._minSuffixComponents = minSuffixComponents
        self._changeCount += 1
        return self

    def setMaxSuffixComponents(self, maxSuffixComponents):
        """
        Set the max suffix components count.

        :param int maxSuffixComponents: The max suffix components count. If not
          specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._maxSuffixComponents = maxSuffixComponents
        self._changeCount += 1
        return self

    def setKeyLocator(self, keyLocator):
        """
        Set this interest to use a copy of the given KeyLocator object.

        :note: You can also call getKeyLocator and change the key locator directly.
        :param KeyLocator keyLocator: The KeyLocator object. This makes a copy
          of the object. If no key locator is specified, set to a new default
          KeyLocator(), or to a KeyLocator with an unspecified type.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._keyLocator.set(
            keyLocator if type(keyLocator) is KeyLocator else KeyLocator())
        self._changeCount += 1
        return self

    def setExclude(self, exclude):
        """
        Set this interest to use a copy of the given Exclude object.

        :note: You can also call getExclude and change the exclude entries directly.
        :param Exclude exclude: The Exclude object. This makes a copy of the
          object. If no exclude is specified, set to a new default Exclude(), or
          to an Exclude with size() 0.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._exclude.set(
            Exclude(exclude) if type(exclude) is Exclude else Exclude())
        self._changeCount += 1
        return self

    def setChildSelector(self, childSelector):
        """
        Set the child selector.

        :param int childSelector: The child selector. If not specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._childSelector = childSelector
        self._changeCount += 1
        return self

    def setMustBeFresh(self, mustBeFresh):
        """
        Set the MustBeFresh flag.

        :param bool mustBeFresh: True if the content must be fresh, otherwise
          False. If you do not set this flag, the default value is true.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._mustBeFresh = True if mustBeFresh else False
        self._changeCount += 1
        return self

    def setNonce(self, nonce):
        """
        :deprecated: You should let the wire encoder generate a random nonce
          internally before sending the interest.
        """
        self._nonce = nonce if type(nonce) is Blob else Blob(nonce)
        # Set _getNonceChangeCount so that the next call to getNonce() won't
        #   clear _nonce.
        self._changeCount += 1
        self._getNonceChangeCount = self.getChangeCount()
        return self

    def setScope(self, scope):
        """
        :deprecated: Scope is not used by NFD.
        """
        if not WireFormat.ENABLE_NDNX:
            raise RuntimeError(
                "setScope is for NDNx and is deprecated. To enable while you upgrade your code to not use Scope, set WireFormat.ENABLE_NDNX = True"
            )

        self._scope = scope
        self._changeCount += 1
        return self

    def setInterestLifetimeMilliseconds(self, interestLifetimeMilliseconds):
        """
        Set the interest lifetime.

        :param float interestLifetimeMilliseconds: The interest lifetime in
          milliseconds. If not specified, set to -1.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._interestLifetimeMilliseconds = (
            None if interestLifetimeMilliseconds == None else
            float(interestLifetimeMilliseconds))
        self._changeCount += 1
        return self

    def wireEncode(self, wireFormat=None):
        """
        Encode this Interest for a particular wire format. If wireFormat is the
        default wire format, also set the defaultWireEncoding field to the
        encoded result.

        :param wireFormat: (optional) A WireFormat object used to encode this
           Interest. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The encoded buffer.
        :rtype: SignedBlob
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if (not self.getDefaultWireEncoding().isNull()
                and self.getDefaultWireEncodingFormat() == wireFormat):
            # We already have an encoding in the desired format.
            return self.getDefaultWireEncoding()

        (encoding, signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.encodeInterest(self)
        wireEncoding = SignedBlob(encoding, signedPortionBeginOffset,
                                  signedPortionEndOffset)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.
            self._setDefaultWireEncoding(wireEncoding,
                                         WireFormat.getDefaultWireFormat())
        return wireEncoding

    def wireDecode(self, input, wireFormat=None):
        """
        Decode the input using a particular wire format and update this Interest.
        If wireFormat is the default wire format, also set the
        defaultWireEncoding to another pointer to the input.

        :param input: The array with the bytes to decode. If input is not a
          Blob, then copy the bytes to save the defaultWireEncoding (otherwise
          take another pointer to the same Blob).
        :type input: A Blob or an array type with int elements
        :param wireFormat: (optional) A WireFormat object used to decode this
           Interest. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        # If input is a Blob, get its buf().
        decodeBuffer = input.buf() if isinstance(input, Blob) else input
        (signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.decodeInterest(self, decodeBuffer)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.  In the Blob constructor, set
            #   copy true, but if input is already a Blob, it won't copy.
            self._setDefaultWireEncoding(
                SignedBlob(Blob(input, True), signedPortionBeginOffset,
                           signedPortionEndOffset),
                WireFormat.getDefaultWireFormat())
        else:
            self._setDefaultWireEncoding(SignedBlob(), None)

    def toUri(self):
        """
        Encode the name according to the "NDN URI Scheme".  If there are
        interest selectors, append "?" and add the selectors as a query string.
        For example "/test/name?ndn.ChildSelector=1".
        :note: This is an experimental feature. See the API docs for more detail at
        http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method .

        :return: The URI string.
        :rtype: string
        """
        selectors = ""
        if self._minSuffixComponents != None:
            selectors += "&ndn.MinSuffixComponents=" + repr(
                self._minSuffixComponents)
        if self._maxSuffixComponents != None:
            selectors += "&ndn.MaxSuffixComponents=" + repr(
                self._maxSuffixComponents)
        if self._childSelector != None:
            selectors += "&ndn.ChildSelector=" + repr(self._childSelector)
        if self._mustBeFresh:
            selectors += "&ndn.MustBeFresh=true"
        if self._scope != None:
            selectors += "&ndn.Scope=" + repr(self._scope)
        if self._interestLifetimeMilliseconds != None:
            selectors += "&ndn.InterestLifetime=" + repr(
                int(round(self._interestLifetimeMilliseconds)))
        if self.getNonce().size() > 0:
            selectors += ("&ndn.Nonce=" +
                          Name.toEscapedString(self.getNonce().buf()))
        if self.getExclude().size() > 0:
            selectors += "&ndn.Exclude=" + self.getExclude().toUri()

        result = self.getName().toUri()
        if selectors != "":
            # Replace the first & with ?.
            result += "?" + selectors[1:]

        return result

    def matchesName(self, name):
        """
        Check if this interest's name matches the given name (using Name.match)
        and the given name also conforms to the interest selectors.

        :param Name name: The name to check.
        :return: True if the name and interest selectors match, False otherwise.
        :rtype: bool
        """
        if not self.getName().match(name):
            return False

        if (self._minSuffixComponents != None and
                # Add 1 for the implicit digest.
                not (name.size() + 1 - self.getName().size() >=
                     self._minSuffixComponents)):
            return False
        if (self._maxSuffixComponents != None and
                # Add 1 for the implicit digest.
                not (name.size() + 1 - self.getName().size() <=
                     self._maxSuffixComponents)):
            return False
        if (self.getExclude().size() > 0
                and name.size() > self.getName().size()
                and self.getExclude().matches(name[self.getName().size()])):
            return False

        return True

    def getDefaultWireEncoding(self):
        """
        Return the default wire encoding, which was encoded with
        getDefaultWireEncodingFormat().

        :return: The default wire encoding, whose isNull() may be true if there
          is no default wire encoding.
        :rtype: SignedBlob
        """
        if self._getDefaultWireEncodingChangeCount != self.getChangeCount():
            # The values have changed, so the default wire encoding is
            # invalidated.
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None
            self._getDefaultWireEncodingChangeCount = self.getChangeCount()

        return self._defaultWireEncoding

    def getDefaultWireEncodingFormat(self):
        """
        Get the WireFormat which is used by getDefaultWireEncoding().

        :return: The WireFormat, which is only meaningful if the
          getDefaultWireEncoding() is not isNull().
        :rtype: WireFormat
        """
        return self._defaultWireEncodingFormat

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._name.checkChanged()
        changed = self._keyLocator.checkChanged() or changed
        changed = self._exclude.checkChanged() or changed
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    def _setDefaultWireEncoding(self, defaultWireEncoding,
                                defaultWireEncodingFormat):
        self._defaultWireEncoding = defaultWireEncoding
        self._defaultWireEncodingFormat = defaultWireEncodingFormat
        # Set _getDefaultWireEncodingChangeCount so that the next call to
        # getDefaultWireEncoding() won't clear _defaultWireEncoding.
        self._getDefaultWireEncodingChangeCount = self.getChangeCount()

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    name = property(getName, setName)
    minSuffixComponents = property(getMinSuffixComponents,
                                   setMinSuffixComponents)
    maxSuffixComponents = property(getMaxSuffixComponents,
                                   setMaxSuffixComponents)
    keyLocator = property(getKeyLocator, setKeyLocator)
    exclude = property(getExclude, setExclude)
    childSelector = property(getChildSelector, setChildSelector)
    mustBeFresh = property(getMustBeFresh, setMustBeFresh)
    nonce = property(getNonce, setNonce)
    scope = property(getScope, setScope)
    interestLifetimeMilliseconds = property(getInterestLifetimeMilliseconds,
                                            setInterestLifetimeMilliseconds)
Ejemplo n.º 11
0
class Data(object):
    def __init__(self, value = None):
        if isinstance(value, Data):
            # Copy the values.
            self._name = ChangeCounter(Name(value.getName()))
            self._metaInfo = ChangeCounter(MetaInfo(value.getMetaInfo()))
            self._signature = ChangeCounter(value.getSignature().clone())
            self._content = value._content
            self._defaultWireEncoding = value.getDefaultWireEncoding()
            self._defaultFullName = value._defaultFullName
            self._defaultWireEncodingFormat = value._defaultWireEncodingFormat
        else:
            self._name = ChangeCounter(Name(value) if type(value) is Name
                                                   else Name())
            self._metaInfo = ChangeCounter(MetaInfo())
            self._signature = ChangeCounter(Sha256WithRsaSignature())
            self._content = Blob()
            self._defaultWireEncoding = SignedBlob()
            self._defaultFullName = Name()
            self._defaultWireEncodingFormat = None

        self._getDefaultWireEncodingChangeCount = 0
        self._changeCount = 0
        self._lpPacket = None

    def wireEncode(self, wireFormat = None):
        """
        Encode this Data for a particular wire format. If wireFormat is the
        default wire format, also set the defaultWireEncoding field to the
        encoded result.

        :param wireFormat: (optional) A WireFormat object used to encode this
           Data object. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The encoded buffer in a SignedBlob object.
        :rtype: SignedBlob
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if (not self.getDefaultWireEncoding().isNull() and
            self.getDefaultWireEncodingFormat() == wireFormat):
            # We already have an encoding in the desired format.
            return self.getDefaultWireEncoding()

        (encoding, signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.encodeData(self)
        wireEncoding = SignedBlob(
          encoding, signedPortionBeginOffset, signedPortionEndOffset)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.
            self._setDefaultWireEncoding(
              wireEncoding, WireFormat.getDefaultWireFormat())
        return wireEncoding

    def wireDecode(self, input, wireFormat = None):
        """
        Decode the input using a particular wire format and update this Data.
        If wireFormat is the default wire format, also set the
        defaultWireEncoding to another pointer to the input.

        :param input: The array with the bytes to decode. If input is not a
          Blob, then copy the bytes to save the defaultWireEncoding (otherwise
          take another pointer to the same Blob).
        :type input: A Blob or an array type with int elements
        :param wireFormat: (optional) A WireFormat object used to decode this
           Data object. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if isinstance(input, Blob):
          # Input is a blob, so get its buf() and set copy False.
          result = wireFormat.decodeData(self, input.buf(), False)
        else:
          result = wireFormat.decodeData(self, input, True)
        (signedPortionBeginOffset, signedPortionEndOffset) = result

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.  In the Blob constructor, set
            #   copy true, but if input is already a Blob, it won't copy.
            self._setDefaultWireEncoding(SignedBlob(
                Blob(input, True),
                signedPortionBeginOffset, signedPortionEndOffset),
            WireFormat.getDefaultWireFormat())
        else:
            self._setDefaultWireEncoding(SignedBlob(), None)

    def getName(self):
        """
        Get the data packet's name.

        :return: The name.
        :rtype: Name
        """
        return self._name.get()

    def getMetaInfo(self):
        """
        Get the data packet's meta info.

        :return: The meta info.
        :rtype: MetaInfo
        """
        return self._metaInfo.get()

    def getSignature(self):
        """
        Get the data packet's signature object.

        :return: The signature object.
        :rtype: a subclass of Signature such as Sha256WithRsaSignature
        """
        return self._signature.get()

    def getContent(self):
        """
        Get the data packet's content.

        :return: The content as a Blob, which isNull() if unspecified.
        :rtype: Blob
        """
        return self._content

    def getDefaultWireEncoding(self):
        """
        Return the default wire encoding, which was encoded with
        getDefaultWireEncodingFormat().

        :return: The default wire encoding, whose isNull() may be true if there
          is no default wire encoding.
        :rtype: SignedBlob
        """
        if self._getDefaultWireEncodingChangeCount != self.getChangeCount():
            # The values have changed, so the default wire encoding is
            # invalidated.
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None
            self._getDefaultWireEncodingChangeCount = self.getChangeCount()

        return self._defaultWireEncoding

    def getDefaultWireEncodingFormat(self):
        """
        Get the WireFormat which is used by getDefaultWireEncoding().

        :return: The WireFormat, which is only meaningful if the
          getDefaultWireEncoding() is not isNull().
        :rtype: WireFormat
        """
        return self._defaultWireEncodingFormat

    def getIncomingFaceId(self):
        """
        Get the incoming face ID according to the incoming packet header.

        :return: The incoming face ID. If not specified, return None.
        :rtype: int
        """
        field = (None if self._lpPacket == None
                 else IncomingFaceId.getFirstHeader(self._lpPacket))
        return None if field == None else field.getFaceId()

    def getFullName(self, wireFormat = None):
        """
        Get the Data packet's full name, which includes the final
        ImplicitSha256Digest component based on the wire encoding for a
        particular wire format.

        :param wireFormat: (optional) A WireFormat object used to encode
           this object. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The full name. You must not change the Name object - if you
          need to change it then make a copy.
        :rtype: Name
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        # The default full name depends on the default wire encoding.
        if (not self.getDefaultWireEncoding().isNull() and
            self._defaultFullName.size() > 0 and
            self.getDefaultWireEncodingFormat() == wireFormat):
            # We already have a full name. A non-null default wire encoding
            # means that the Data packet fields have not changed.
            return self._defaultFullName

        fullName = Name(self.getName())
        sha256 = hashes.Hash(hashes.SHA256(), backend=default_backend())
        sha256.update(self.wireEncode(wireFormat).toBytes())
        fullName.appendImplicitSha256Digest(
          Blob(bytearray(sha256.finalize()), False))

        if wireFormat == WireFormat.getDefaultWireFormat():
          # wireEncode has already set defaultWireEncodingFormat_.
          self._defaultFullName = fullName

        return fullName

    def setName(self, name):
        """
        Set name to a copy of the given Name.

        :param Name name: The Name which is copied.
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._name.set(name if type(name) is Name else Name(name))
        self._changeCount += 1
        return self

    def setMetaInfo(self, metaInfo):
        """
        Set metaInfo to a copy of the given MetaInfo.

        :param MetaInfo metaInfo: The MetaInfo which is copied.
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._metaInfo.set(MetaInfo() if metaInfo == None
                                      else MetaInfo(metaInfo))
        self._changeCount += 1
        return self

    def setSignature(self, signature):
        """
        Set the signature to a copy of the given signature.

        :param signature: The signature object which is cloned.
        :type signature: a subclass of Signature such as Sha256WithRsaSignature
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._signature.set(Sha256WithRsaSignature() if signature == None
                                                     else signature.clone())
        self._changeCount += 1
        return self

    def setContent(self, content):
        """
        Set the content to the given value.

        :param content: The array with the content bytes. If content is not a
          Blob, then create a new Blob to copy the bytes (otherwise
          take another pointer to the same Blob).
        :type content: A Blob or an array type with int elements
        """
        self._content = content if isinstance(content, Blob) else Blob(content)
        self._changeCount += 1

    def setLpPacket(self, lpPacket):
        """
        An internal library method to set the LpPacket for an incoming packet.
        The application should not call this.

        :param LpPacket lpPacket: The LpPacket. This does not make a copy.
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        :note: This is an experimental feature. This API may change in the future.
        """
        self._lpPacket = lpPacket
        # Don't update _changeCount since this doesn't affect the wire encoding.
        return self

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._name.checkChanged()
        changed = self._metaInfo.checkChanged() or changed
        changed = self._signature.checkChanged() or changed
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    def _setDefaultWireEncoding(
          self, defaultWireEncoding, defaultWireEncodingFormat):
        self._defaultWireEncoding = defaultWireEncoding
        self._defaultWireEncodingFormat = defaultWireEncodingFormat
        # Set _getDefaultWireEncodingChangeCount so that the next call to
        # getDefaultWireEncoding() won't clear _defaultWireEncoding.
        self._getDefaultWireEncodingChangeCount = self.getChangeCount()

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    name = property(getName, setName)
    metaInfo = property(getMetaInfo, setMetaInfo)
    signature = property(getSignature, setSignature)
    content = property(getContent, setContent)
Ejemplo n.º 12
0
class Interest(object):
    def __init__(self, value=None):
        if type(value) is Interest:
            # Copy the values.
            self._name = ChangeCounter(Name(value.getName()))
            self._minSuffixComponents = value._minSuffixComponents
            self._maxSuffixComponents = value._maxSuffixComponents
            self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator()))
            self._exclude = ChangeCounter(Exclude(value.getExclude()))
            self._childSelector = value._childSelector
            self._mustBeFresh = value._mustBeFresh

            self._nonce = value.getNonce()
            self._scope = value._scope
            self._interestLifetimeMilliseconds = value._interestLifetimeMilliseconds
            self._defaultWireEncoding = value.getDefaultWireEncoding()
            self._defaultWireEncodingFormat = value._defaultWireEncodingFormat
        else:
            self._name = ChangeCounter(Name(value) if type(value) is Name else Name())
            self._minSuffixComponents = None
            self._maxSuffixComponents = None
            self._keyLocator = ChangeCounter(KeyLocator())
            self._exclude = ChangeCounter(Exclude())
            self._childSelector = None
            self._mustBeFresh = True

            self._nonce = Blob()
            self._scope = None
            self._interestLifetimeMilliseconds = None
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None

        self._getNonceChangeCount = 0
        self._getDefaultWireEncodingChangeCount = 0
        self._changeCount = 0

    def getName(self):
        """
        Get the interest Name.
        
        :return: The name.  The name size() may be 0 if not specified.
        :rtype: Name
        """
        return self._name.get()

    def getMinSuffixComponents(self):
        """
        Get the min suffix components.
        
        :return: The min suffix components, or None if not specified.
        :rtype: int
        """
        return self._minSuffixComponents

    def getMaxSuffixComponents(self):
        """
        Get the max suffix components.
        
        :return: The max suffix components, or None if not specified.
        :rtype: int
        """
        return self._maxSuffixComponents

    def getKeyLocator(self):
        """
        Get the interest key locator.
        
        :return: The key locator. If getType() is None, then the key locator
          is not specified.
        :rtype: KeyLocator
        """
        return self._keyLocator.get()

    def getExclude(self):
        """
        Get the exclude object.
        
        :return: The exclude object. If the exclude size() is zero, then
          the exclude is not specified.
        :rtype: Exclude
        """
        return self._exclude.get()

    def getChildSelector(self):
        """
        Get the child selector.
        
        :return: The child selector, or None if not specified.
        :rtype: int
        """
        return self._childSelector

    def getMustBeFresh(self):
        """
        Get the must be fresh flag.
        
        :return: The must be fresh flag.  If not specified, the default is 
          True.
        :rtype: bool
        """
        return self._mustBeFresh

    def getNonce(self):
        """
        Return the nonce value from the incoming interest.  If you change any of
        the fields in this Interest object, then the nonce value is cleared.
        
        :return: The nonce.  If isNull() then the nonce is omitted.
        :rtype: Blob
        """
        if self._getNonceChangeCount != self.getChangeCount():
            # The values have changed, so the existing nonce is invalidated.
            self._nonce = Blob()
            self._getNonceChangeCount = self.getChangeCount()

        return self._nonce

    def getScope(self):
        """
        Get the interest scope.
        
        :return: The scope, or None if not specified.
        :rtype: int
        """
        return self._scope

    def getInterestLifetimeMilliseconds(self):
        """
        Get the interest lifetime.
        
        :return: The interest lifetime in milliseconds, or None if not specified.
        :rtype: float
        """
        return self._interestLifetimeMilliseconds

    def setName(self, name):
        self._name.set(name if type(name) is Name else Name(name))
        self._changeCount += 1

    def setMinSuffixComponents(self, minSuffixComponents):
        self._minSuffixComponents = minSuffixComponents
        self._changeCount += 1

    def setMaxSuffixComponents(self, maxSuffixComponents):
        self._maxSuffixComponents = maxSuffixComponents
        self._changeCount += 1

    def setKeyLocator(self, keyLocator):
        """
        Set this interest to use a copy of the given keyLocator.
        Note: You can also change this interest's key locator modifying
        the object from getKeyLocator().
        
        :param KeyLocator keyLocator: The KeyLocator that is copied.
        """
        self._keyLocator.set(keyLocator if type(keyLocator) is KeyLocator else KeyLocator())
        self._changeCount += 1

    def setExclude(self, exclude):
        """
        Set this interest to use a copy of the given exclude object.
        Note: You can also change this interest's exclude object modifying
        the object from getExclude().
        
        :param Exclude exclude: The exlcude object that is copied.
        """
        self._exclude.set(Exclude(exclude) if type(exclude) is Exclude else Exclude())
        self._changeCount += 1

    def setChildSelector(self, childSelector):
        self._childSelector = childSelector
        self._changeCount += 1

    def setMustBeFresh(self, mustBeFresh):
        self._mustBeFresh = True if mustBeFresh else False
        self._changeCount += 1

    def setNonce(self, nonce):
        self._nonce = nonce if type(nonce) is Blob else Blob(nonce)
        # Set _getNonceChangeCount so that the next call to getNonce() won't
        #   clear _nonce.
        self._changeCount += 1
        self._getNonceChangeCount = self.getChangeCount()

    def setScope(self, scope):
        self._scope = scope
        self._changeCount += 1

    def setInterestLifetimeMilliseconds(self, interestLifetimeMilliseconds):
        self._interestLifetimeMilliseconds = (
            None if interestLifetimeMilliseconds == None else float(interestLifetimeMilliseconds)
        )
        self._changeCount += 1

    def wireEncode(self, wireFormat=None):
        """
        Encode this Interest for a particular wire format. If wireFormat is the
        default wire format, also set the defaultWireEncoding field to the
        encoded result.
        
        :param wireFormat: (optional) A WireFormat object used to encode this 
           Interest. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The encoded buffer.
        :rtype: Blob
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if not self.getDefaultWireEncoding().isNull() and self.getDefaultWireEncodingFormat() == wireFormat:
            # We already have an encoding in the desired format.
            return self.getDefaultWireEncoding()

        (encoding, signedPortionBeginOffset, signedPortionEndOffset) = wireFormat.encodeInterest(self)
        wireEncoding = SignedBlob(encoding, signedPortionBeginOffset, signedPortionEndOffset)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.
            self._setDefaultWireEncoding(wireEncoding, WireFormat.getDefaultWireFormat())
        return wireEncoding

    def wireDecode(self, input, wireFormat=None):
        """
        Decode the input using a particular wire format and update this Interest.
        If wireFormat is the default wire format, also set the
        defaultWireEncoding to another pointer to the input.
        
        :param input: The array with the bytes to decode. If input is not a
          Blob, then copy the bytes to save the defaultWireEncoding (otherwise
          take another pointer to the same Blob).
        :type input: A Blob or an array type with int elements
        :param wireFormat: (optional) A WireFormat object used to decode this 
           Interest. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        # If input is a Blob, get its buf().
        decodeBuffer = input.buf() if isinstance(input, Blob) else input
        (signedPortionBeginOffset, signedPortionEndOffset) = wireFormat.decodeInterest(self, decodeBuffer)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.  In the Blob constructor, set
            #   copy true, but if input is already a Blob, it won't copy.
            self._setDefaultWireEncoding(
                SignedBlob(Blob(input, True), signedPortionBeginOffset, signedPortionEndOffset),
                WireFormat.getDefaultWireFormat(),
            )
        else:
            self._setDefaultWireEncoding(SignedBlob(), None)

    def toUri(self):
        """
        Encode the name according to the "NDN URI Scheme".  If there are 
        interest selectors, append "?" and add the selectors as a query string.  
        For example "/test/name?ndn.ChildSelector=1".
        :note: This is an experimental feature. See the API docs for more detail at 
        http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method .
        
        :return: The URI string.
        :rtype: string
        """
        selectors = ""
        if self._minSuffixComponents != None:
            selectors += "&ndn.MinSuffixComponents=" + repr(self._minSuffixComponents)
        if self._maxSuffixComponents != None:
            selectors += "&ndn.MaxSuffixComponents=" + repr(self._maxSuffixComponents)
        if self._childSelector != None:
            selectors += "&ndn.ChildSelector=" + repr(self._childSelector)
        if self._mustBeFresh:
            selectors += "&ndn.MustBeFresh=true"
        if self._scope != None:
            selectors += "&ndn.Scope=" + repr(self._scope)
        if self._interestLifetimeMilliseconds != None:
            selectors += "&ndn.InterestLifetime=" + repr(int(round(self._interestLifetimeMilliseconds)))
        if self.getNonce().size() > 0:
            selectors += "&ndn.Nonce=" + Name.toEscapedString(self.getNonce().buf())
        if self.getExclude().size() > 0:
            selectors += "&ndn.Exclude=" + self.getExclude().toUri()

        result = self.getName().toUri()
        if selectors != "":
            # Replace the first & with ?.
            result += "?" + selectors[1:]

        return result

    def matchesName(self, name):
        """
        Check if this interest's name matches the given name (using Name.match) 
        and the given name also conforms to the interest selectors.
        
        :param Name name: The name to check.
        :return: True if the name and interest selectors match, False otherwise.
        :rtype: bool
        """
        if not self.getName().match(name):
            return False

        if (
            self._minSuffixComponents != None
            and
            # Add 1 for the implicit digest.
            not (name.size() + 1 - self.getName().size() >= self._minSuffixComponents)
        ):
            return False
        if (
            self._maxSuffixComponents != None
            and
            # Add 1 for the implicit digest.
            not (name.size() + 1 - self.getName().size() <= self._maxSuffixComponents)
        ):
            return False
        if (
            self.getExclude().size() > 0
            and name.size() > self.getName().size()
            and self.getExclude().matches(name[self.getName().size()])
        ):
            return False

        return True

    def getDefaultWireEncoding(self):
        """
        Return the default wire encoding, which was encoded with
        getDefaultWireEncodingFormat().

        :return: The default wire encoding, whose isNull() may be true if there
          is no default wire encoding.
        :rtype: SignedBlob
        """
        if self._getDefaultWireEncodingChangeCount != self.getChangeCount():
            # The values have changed, so the default wire encoding is
            # invalidated.
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None
            self._getDefaultWireEncodingChangeCount = self.getChangeCount()

        return self._defaultWireEncoding

    def getDefaultWireEncodingFormat(self):
        """
        Get the WireFormat which is used by getDefaultWireEncoding().

        :return: The WireFormat, which is only meaningful if the
          getDefaultWireEncoding() is not isNull().
        :rtype: WireFormat
        """
        return self._defaultWireEncodingFormat

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object 
        (or a child object) is changed.
        
        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._name.checkChanged()
        changed = self._keyLocator.checkChanged() or changed
        changed = self._exclude.checkChanged() or changed
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    def _setDefaultWireEncoding(self, defaultWireEncoding, defaultWireEncodingFormat):
        self._defaultWireEncoding = defaultWireEncoding
        self._defaultWireEncodingFormat = defaultWireEncodingFormat
        # Set _getDefaultWireEncodingChangeCount so that the next call to
        # getDefaultWireEncoding() won't clear _defaultWireEncoding.
        self._getDefaultWireEncodingChangeCount = self.getChangeCount()

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    name = property(getName, setName)
    minSuffixComponents = property(getMinSuffixComponents, setMinSuffixComponents)
    maxSuffixComponents = property(getMaxSuffixComponents, setMaxSuffixComponents)
    keyLocator = property(getKeyLocator, setKeyLocator)
    exclude = property(getExclude, setExclude)
    childSelector = property(getChildSelector, setChildSelector)
    mustBeFresh = property(getMustBeFresh, setMustBeFresh)
    nonce = property(getNonce, setNonce)
    scope = property(getScope, setScope)
    interestLifetimeMilliseconds = property(getInterestLifetimeMilliseconds, setInterestLifetimeMilliseconds)
Ejemplo n.º 13
0
class Interest(object):
    def __init__(self, value = None):
        if type(value) is Interest:
            # Copy the values.
            self._name = ChangeCounter(Name(value.getName()))
            self._minSuffixComponents = value._minSuffixComponents
            self._maxSuffixComponents = value._maxSuffixComponents
            self._keyLocator = ChangeCounter(KeyLocator(value.getKeyLocator()))
            self._exclude = ChangeCounter(Exclude(value.getExclude()))
            self._childSelector = value._childSelector
            self._mustBeFresh = value._mustBeFresh

            self._nonce = value.getNonce()
            self._interestLifetimeMilliseconds = value._interestLifetimeMilliseconds
            self._linkWireEncoding = value._linkWireEncoding
            self._linkWireEncodingFormat = value._linkWireEncodingFormat
            self._link = ChangeCounter(None)
            if value._link.get() != None:
              self._link.set(Link(value._link.get()))
            self._selectedDelegationIndex = value._selectedDelegationIndex
            self._defaultWireEncoding = value.getDefaultWireEncoding()
            self._defaultWireEncodingFormat = value._defaultWireEncodingFormat
        else:
            self._name = ChangeCounter(Name(value) if type(value) is Name
                                                   else Name())
            self._minSuffixComponents = None
            self._maxSuffixComponents = None
            self._keyLocator = ChangeCounter(KeyLocator())
            self._exclude = ChangeCounter(Exclude())
            self._childSelector = None
            self._mustBeFresh = True

            self._nonce = Blob()
            self._interestLifetimeMilliseconds = None
            self._linkWireEncoding = Blob()
            self._linkWireEncodingFormat = None
            self._link = ChangeCounter(None)
            self._selectedDelegationIndex = None
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None

        self._getNonceChangeCount = 0
        self._getDefaultWireEncodingChangeCount = 0
        self._changeCount = 0
        self._lpPacket = None

    def getName(self):
        """
        Get the interest Name.

        :return: The name.  The name size() may be 0 if not specified.
        :rtype: Name
        """
        return self._name.get()

    def getMinSuffixComponents(self):
        """
        Get the min suffix components.

        :return: The min suffix components, or None if not specified.
        :rtype: int
        """
        return self._minSuffixComponents

    def getMaxSuffixComponents(self):
        """
        Get the max suffix components.

        :return: The max suffix components, or None if not specified.
        :rtype: int
        """
        return self._maxSuffixComponents

    def getKeyLocator(self):
        """
        Get the interest key locator.

        :return: The key locator. If getType() is None, then the key locator
          is not specified.
        :rtype: KeyLocator
        """
        return self._keyLocator.get()

    def getExclude(self):
        """
        Get the exclude object.

        :return: The exclude object. If the exclude size() is zero, then
          the exclude is not specified.
        :rtype: Exclude
        """
        return self._exclude.get()

    def getChildSelector(self):
        """
        Get the child selector.

        :return: The child selector, or None if not specified.
        :rtype: int
        """
        return self._childSelector

    def getMustBeFresh(self):
        """
        Get the must be fresh flag.

        :return: The must be fresh flag.  If not specified, the default is
          True.
        :rtype: bool
        """
        return self._mustBeFresh

    def getNonce(self):
        """
        Return the nonce value from the incoming interest.  If you change any of
        the fields in this Interest object, then the nonce value is cleared.

        :return: The nonce.  If isNull() then the nonce is omitted.
        :rtype: Blob
        """
        if self._getNonceChangeCount != self.getChangeCount():
            # The values have changed, so the existing nonce is invalidated.
            self._nonce = Blob()
            self._getNonceChangeCount = self.getChangeCount()

        return self._nonce

    def hasLink(self):
        """
        Check if this interest has a link object (or a link wire encoding which
        can be decoded to make the link object).

        :return:  True if this interest has a link object, False if not.
        :rtype: bool
        """
        return self._link.get() != None or not self._linkWireEncoding.isNull()

    def getLink(self):
        """
        Get the link object. If necessary, decode it from the link wire encoding.

        :return: The link object, or null if not specified.
        :rtype: Link
        :raises ValueError: For error decoding the link wire encoding (if
          necessary).
        """
        if self._link.get() != None:
            return self._link.get()
        elif not self._linkWireEncoding.isNull():
            # Decode the link object from linkWireEncoding_.
            link = Link()
            link.wireDecode(self._linkWireEncoding, self._linkWireEncodingFormat)
            self._link.set(link)

            # Clear _linkWireEncoding since it is now managed by the link object.
            self._linkWireEncoding = Blob()
            self._linkWireEncodingFormat = None

            return link
        else:
            return None

    def getLinkWireEncoding(self, wireFormat = None):
        """
        Get the wire encoding of the link object. If there is already a wire
        encoding then return it. Otherwise encode from the link object (if
        available).

        :param WireFormat wireFormat: (optional) A WireFormat object used to
          encode the Link. If omitted, use WireFormat.getDefaultWireFormat().
        :return: The wire encoding, or an isNull Blob if the link is not
          specified.
        :rtype: Blob
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if (not self._linkWireEncoding.isNull() and
            self._linkWireEncodingFormat == wireFormat):
          return self._linkWireEncoding

        link = self.getLink()
        if link != None:
          return link.wireEncode(wireFormat)
        else:
          return Blob()

    def getSelectedDelegationIndex(self):
        """
        Get the selected delegation index.

        :return: The selected delegation index. If not specified, return None.
        :rtype: int
        """
        return self._selectedDelegationIndex

    def getInterestLifetimeMilliseconds(self):
        """
        Get the interest lifetime.

        :return: The interest lifetime in milliseconds, or None if not specified.
        :rtype: float
        """
        return self._interestLifetimeMilliseconds

    def getIncomingFaceId(self):
        """
        Get the incoming face ID according to the incoming packet header.

        :return: The incoming face ID. If not specified, return None.
        :rtype: int
        """
        field = (None if self._lpPacket == None
                 else IncomingFaceId.getFirstHeader(self._lpPacket))
        return None if field == None else field.getFaceId()

    def setName(self, name):
        """
        Set the interest name.

        :note: You can also call getName and change the name values directly.
        :param Name name: The interest name. This makes a copy of the name.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._name.set(name if type(name) is Name else Name(name))
        self._changeCount += 1
        return self

    def setMinSuffixComponents(self, minSuffixComponents):
        """
        Set the min suffix components count.

        :param int minSuffixComponents: The min suffix components count. If not
          specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._minSuffixComponents = Common.nonNegativeIntOrNone(minSuffixComponents)
        self._changeCount += 1
        return self

    def setMaxSuffixComponents(self, maxSuffixComponents):
        """
        Set the max suffix components count.

        :param int maxSuffixComponents: The max suffix components count. If not
          specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._maxSuffixComponents = Common.nonNegativeIntOrNone(maxSuffixComponents)
        self._changeCount += 1
        return self

    def setKeyLocator(self, keyLocator):
        """
        Set this interest to use a copy of the given KeyLocator object.

        :note: You can also call getKeyLocator and change the key locator directly.
        :param KeyLocator keyLocator: The KeyLocator object. This makes a copy
          of the object. If no key locator is specified, set to a new default
          KeyLocator(), or to a KeyLocator with an unspecified type.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._keyLocator.set(
          KeyLocator(keyLocator) if type(keyLocator) is KeyLocator
                     else KeyLocator())
        self._changeCount += 1
        return self

    def setExclude(self, exclude):
        """
        Set this interest to use a copy of the given Exclude object.

        :note: You can also call getExclude and change the exclude entries directly.
        :param Exclude exclude: The Exclude object. This makes a copy of the
          object. If no exclude is specified, set to a new default Exclude(), or
          to an Exclude with size() 0.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._exclude.set(
          Exclude(exclude) if type(exclude) is Exclude else Exclude())
        self._changeCount += 1
        return self

    def setLinkWireEncoding(self, encoding, wireFormat = None):
        """
        Set the link wire encoding bytes, without decoding them. If there is a
        link object, set it to null. If you later call getLink(), it will decode
        the wireEncoding to create the link object.

        :param Blob encoding: The Blob with the bytes of the link wire encoding.
          If no link is specified, set to an empty Blob() or call unsetLink().
        :param WireFormat wireFormat: The wire format of the encoding, to be
          used later if necessary to decode. If omitted, use
          WireFormat.getDefaultWireFormat().
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        self._linkWireEncoding = encoding
        self._linkWireEncodingFormat = wireFormat

        # Clear the link object, assuming that it has a different encoding.
        self._link.set(None)

        self._changeCount += 1
        return self

    def unsetLink(self):
        """
        Clear the link wire encoding and link object so that getLink() returns
        None.

        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        return self.setLinkWireEncoding(Blob(), None)

    def setSelectedDelegationIndex(self, selectedDelegationIndex):
        """
        Set the selected delegation index.

        :param int selectedDelegationIndex: The selected delegation index. If
          not specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._selectedDelegationIndex = Common.nonNegativeIntOrNone(selectedDelegationIndex)
        self._changeCount += 1
        return self

    def setChildSelector(self, childSelector):
        """
        Set the child selector.

        :param int childSelector: The child selector. If not specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._childSelector = Common.nonNegativeIntOrNone(childSelector)
        self._changeCount += 1
        return self

    def setMustBeFresh(self, mustBeFresh):
        """
        Set the MustBeFresh flag.

        :param bool mustBeFresh: True if the content must be fresh, otherwise
          False. If you do not set this flag, the default value is true.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._mustBeFresh = True if mustBeFresh else False
        self._changeCount += 1
        return self

    def setNonce(self, nonce):
        """
        :deprecated: You should let the wire encoder generate a random nonce
          internally before sending the interest.
        """
        self._nonce = nonce if isinstance(nonce, Blob) else Blob(nonce)
        # Set _getNonceChangeCount so that the next call to getNonce() won't
        #   clear _nonce.
        self._changeCount += 1
        self._getNonceChangeCount = self.getChangeCount()
        return self

    def setInterestLifetimeMilliseconds(self, interestLifetimeMilliseconds):
        """
        Set the interest lifetime.

        :param float interestLifetimeMilliseconds: The interest lifetime in
          milliseconds. If not specified, set to None.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        """
        self._interestLifetimeMilliseconds = Common.nonNegativeFloatOrNone(
          interestLifetimeMilliseconds)
        self._changeCount += 1
        return self

    def wireEncode(self, wireFormat = None):
        """
        Encode this Interest for a particular wire format. If wireFormat is the
        default wire format, also set the defaultWireEncoding field to the
        encoded result.

        :param wireFormat: (optional) A WireFormat object used to encode this
           Interest. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The encoded buffer.
        :rtype: SignedBlob
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if (not self.getDefaultWireEncoding().isNull() and
            self.getDefaultWireEncodingFormat() == wireFormat):
            # We already have an encoding in the desired format.
            return self.getDefaultWireEncoding()

        (encoding, signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.encodeInterest(self)
        wireEncoding = SignedBlob(
          encoding, signedPortionBeginOffset, signedPortionEndOffset)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.
            self._setDefaultWireEncoding(
              wireEncoding, WireFormat.getDefaultWireFormat())
        return wireEncoding

    def wireDecode(self, input, wireFormat = None):
        """
        Decode the input using a particular wire format and update this Interest.
        If wireFormat is the default wire format, also set the
        defaultWireEncoding to another pointer to the input.

        :param input: The array with the bytes to decode. If input is not a
          Blob, then copy the bytes to save the defaultWireEncoding (otherwise
          take another pointer to the same Blob).
        :type input: A Blob or an array type with int elements
        :param wireFormat: (optional) A WireFormat object used to decode this
           Interest. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if isinstance(input, Blob):
          # Input is a blob, so get its buf() and set copy False.
          result = wireFormat.decodeInterest(self, input.buf(), False)
        else:
          result = wireFormat.decodeInterest(self, input, True)
        (signedPortionBeginOffset, signedPortionEndOffset) = result

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.  In the Blob constructor, set
            #   copy true, but if input is already a Blob, it won't copy.
            self._setDefaultWireEncoding(SignedBlob(
                Blob(input, True),
                signedPortionBeginOffset, signedPortionEndOffset),
            WireFormat.getDefaultWireFormat())
        else:
            self._setDefaultWireEncoding(SignedBlob(), None)

    def toUri(self):
        """
        Encode the name according to the "NDN URI Scheme".  If there are
        interest selectors, append "?" and add the selectors as a query string.
        For example "/test/name?ndn.ChildSelector=1".
        :note: This is an experimental feature. See the API docs for more detail at
        http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method .

        :return: The URI string.
        :rtype: string
        """
        selectors = ""
        if self._minSuffixComponents != None:
            selectors += "&ndn.MinSuffixComponents=" + repr(
              self._minSuffixComponents)
        if self._maxSuffixComponents != None:
            selectors += "&ndn.MaxSuffixComponents=" + repr(
              self._maxSuffixComponents)
        if self._childSelector != None:
            selectors += "&ndn.ChildSelector=" + repr(self._childSelector)
        if self._mustBeFresh:
            selectors += "&ndn.MustBeFresh=true"
        if self._interestLifetimeMilliseconds != None:
            selectors += "&ndn.InterestLifetime=" + repr(
              int(round(self._interestLifetimeMilliseconds)))
        if self.getNonce().size() > 0:
            selectors += ("&ndn.Nonce=" +
              Name.toEscapedString(self.getNonce().buf()))
        if self.getExclude().size() > 0:
            selectors += "&ndn.Exclude=" + self.getExclude().toUri()

        result = self.getName().toUri()
        if selectors != "":
            # Replace the first & with ?.
            result += "?" + selectors[1:]

        return result

    def refreshNonce(self):
        """
        Update the bytes of the nonce with new random values. This ensures that
        the new nonce value is different than the current one. If the current
        nonce is not specified, this does nothing.
        """
        currentNonce = self.getNonce()
        if currentNonce.size() == 0:
            return

        while True:
            value = bytearray(currentNonce.size())
            for i in range(len(value)):
                value[i] = self._systemRandom.randint(0, 0xff)
            newNonce = Blob(value, False)
            if newNonce != currentNonce:
                break

        self._nonce = newNonce
        # Set _getNonceChangeCount so that the next call to getNonce() won't
        #   clear _nonce.
        self._changeCount += 1
        self._getNonceChangeCount = self.getChangeCount()

    def matchesName(self, name):
        """
        Check if this interest's name matches the given name (using Name.match)
        and the given name also conforms to the interest selectors.

        :param Name name: The name to check.
        :return: True if the name and interest selectors match, False otherwise.
        :rtype: bool
        """
        if not self.getName().match(name):
            return False

        if (self._minSuffixComponents != None and
              # Add 1 for the implicit digest.
              not (name.size() + 1 - self.getName().size() >=
                   self._minSuffixComponents)):
            return False
        if (self._maxSuffixComponents != None and
              # Add 1 for the implicit digest.
              not (name.size() + 1 - self.getName().size() <=
                   self._maxSuffixComponents)):
            return False
        if (self.getExclude().size() > 0 and
              name.size() > self.getName().size() and
              self.getExclude().matches(name[self.getName().size()])):
            return False

        return True

    def matchesData(self, data, wireFormat = None):
        """
        Check if the given Data packet can satisfy this Interest. This method
        considers the Name, MinSuffixComponents, MaxSuffixComponents,
        PublisherPublicKeyLocator, and Exclude. It does not consider the
        ChildSelector or MustBeFresh. This uses the given wireFormat to get the
        Data packet encoding for the full Name.

        :param Data data: The Data packet to check.
        :param wireFormat: (optional) A WireFormat object used to encode the
          Data packet to get its full Name. If omitted, use
          WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: True if the given Data packet can satisfy this Interest.
        :rtype: bool
        """
        # Imitate ndn-cxx Interest::matchesData.
        interestNameLength = self.getName().size()
        dataName = data.getName()
        fullNameLength = dataName.size() + 1

        # Check MinSuffixComponents.
        hasMinSuffixComponents = (self.getMinSuffixComponents() != None)
        minSuffixComponents = (self.getMinSuffixComponents() if
          hasMinSuffixComponents else 0)
        if not (interestNameLength + minSuffixComponents <= fullNameLength):
            return False

        # Check MaxSuffixComponents.
        hasMaxSuffixComponents = (self.getMaxSuffixComponents() != None)
        if (hasMaxSuffixComponents and
             not (interestNameLength + self.getMaxSuffixComponents() >= fullNameLength)):
            return False

        # Check the prefix.
        if interestNameLength == fullNameLength:
            if self.getName().get(-1).isImplicitSha256Digest():
                if not self.getName().equals(data.getFullName(wireFormat)):
                    return False
            else:
                # The Interest Name is the same length as the Data full Name,
                #   but the last component isn't a digest so there's no
                #   possibility of matching.
                return False
        else:
            # The Interest Name should be a strict prefix of the Data full Name.
            if not self.getName().isPrefixOf(dataName):
                return False

        # Check the Exclude.
        # The Exclude won't be violated if the Interest Name is the same as the
        #   Data full Name.
        if self.getExclude().size() > 0 and fullNameLength > interestNameLength:
            if interestNameLength == fullNameLength - 1:
                # The component to exclude is the digest.
                if self.getExclude().matches(
                     data.getFullName(wireFormat).get(interestNameLength)):
                    return False
            else:
                # The component to exclude is not the digest.
                if self.getExclude().matches(dataName.get(interestNameLength)):
                    return False

        # Check the KeyLocator.
        publisherPublicKeyLocator = self.getKeyLocator()
        if publisherPublicKeyLocator.getType() != None:
            signature = data.getSignature()
            if not KeyLocator.canGetFromSignature(signature):
                # No KeyLocator in the Data packet.
                return False
            if not publisherPublicKeyLocator.equals(
                  (KeyLocator.getFromSignature(signature))):
                return False

        return True

    def getDefaultWireEncoding(self):
        """
        Return the default wire encoding, which was encoded with
        getDefaultWireEncodingFormat().

        :return: The default wire encoding, whose isNull() may be true if there
          is no default wire encoding.
        :rtype: SignedBlob
        """
        if self._getDefaultWireEncodingChangeCount != self.getChangeCount():
            # The values have changed, so the default wire encoding is
            # invalidated.
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None
            self._getDefaultWireEncodingChangeCount = self.getChangeCount()

        return self._defaultWireEncoding

    def getDefaultWireEncodingFormat(self):
        """
        Get the WireFormat which is used by getDefaultWireEncoding().

        :return: The WireFormat, which is only meaningful if the
          getDefaultWireEncoding() is not isNull().
        :rtype: WireFormat
        """
        return self._defaultWireEncodingFormat

    def setLpPacket(self, lpPacket):
        """
        An internal library method to set the LpPacket for an incoming packet.
        The application should not call this.

        :param LpPacket lpPacket: The LpPacket. This does not make a copy.
        :return: This Interest so that you can chain calls to update values.
        :rtype: Interest
        :note: This is an experimental feature. This API may change in the future.
        """
        self._lpPacket = lpPacket
        # Don't update _changeCount since this doesn't affect the wire encoding.
        return self

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._name.checkChanged()
        changed = self._keyLocator.checkChanged() or changed
        changed = self._exclude.checkChanged() or changed
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    def _setDefaultWireEncoding(
          self, defaultWireEncoding, defaultWireEncodingFormat):
        self._defaultWireEncoding = defaultWireEncoding
        self._defaultWireEncodingFormat = defaultWireEncodingFormat
        # Set _getDefaultWireEncodingChangeCount so that the next call to
        # getDefaultWireEncoding() won't clear _defaultWireEncoding.
        self._getDefaultWireEncodingChangeCount = self.getChangeCount()

    _systemRandom = SystemRandom()

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    name = property(getName, setName)
    minSuffixComponents = property(getMinSuffixComponents, setMinSuffixComponents)
    maxSuffixComponents = property(getMaxSuffixComponents, setMaxSuffixComponents)
    keyLocator = property(getKeyLocator, setKeyLocator)
    exclude = property(getExclude, setExclude)
    childSelector = property(getChildSelector, setChildSelector)
    mustBeFresh = property(getMustBeFresh, setMustBeFresh)
    nonce = property(getNonce, setNonce)
    interestLifetimeMilliseconds = property(getInterestLifetimeMilliseconds, setInterestLifetimeMilliseconds)
Ejemplo n.º 14
0
class Data(object):
    def __init__(self, value=None):
        if isinstance(value, Data):
            # Copy the values.
            self._name = ChangeCounter(Name(value.getName()))
            self._metaInfo = ChangeCounter(MetaInfo(value.getMetaInfo()))
            self._signature = ChangeCounter(value.getSignature().clone())
            self._content = value._content
            self._defaultWireEncoding = value.getDefaultWireEncoding()
            self._defaultWireEncodingFormat = value._defaultWireEncodingFormat
        else:
            self._name = ChangeCounter(
                Name(value) if type(value) is Name else Name())
            self._metaInfo = ChangeCounter(MetaInfo())
            self._signature = ChangeCounter(Sha256WithRsaSignature())
            self._content = Blob()
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None

        self._getDefaultWireEncodingChangeCount = 0
        self._changeCount = 0

    def wireEncode(self, wireFormat=None):
        """
        Encode this Data for a particular wire format. If wireFormat is the 
        default wire format, also set the defaultWireEncoding field to the 
        encoded result.
        
        :param wireFormat: (optional) A WireFormat object used to encode this 
           Data object. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        :return: The encoded buffer in a SignedBlob object.
        :rtype: SignedBlob
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        if (not self.getDefaultWireEncoding().isNull()
                and self.getDefaultWireEncodingFormat() == wireFormat):
            # We already have an encoding in the desired format.
            return self.getDefaultWireEncoding()

        (encoding, signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.encodeData(self)
        wireEncoding = SignedBlob(encoding, signedPortionBeginOffset,
                                  signedPortionEndOffset)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.
            self._setDefaultWireEncoding(wireEncoding,
                                         WireFormat.getDefaultWireFormat())
        return wireEncoding

    def wireDecode(self, input, wireFormat=None):
        """
        Decode the input using a particular wire format and update this Data. 
        If wireFormat is the default wire format, also set the 
        defaultWireEncoding to another pointer to the input.
        
        :param input: The array with the bytes to decode. If input is not a 
          Blob, then copy the bytes to save the defaultWireEncoding (otherwise 
          take another pointer to the same Blob).
        :type input: A Blob or an array type with int elements 
        :param wireFormat: (optional) A WireFormat object used to decode this 
           Data object. If omitted, use WireFormat.getDefaultWireFormat().
        :type wireFormat: A subclass of WireFormat
        """
        if wireFormat == None:
            # Don't use a default argument since getDefaultWireFormat can change.
            wireFormat = WireFormat.getDefaultWireFormat()

        # If input is a blob, get its buf().
        decodeBuffer = input.buf() if isinstance(input, Blob) else input
        (signedPortionBeginOffset, signedPortionEndOffset) = \
          wireFormat.decodeData(self, decodeBuffer)

        if wireFormat == WireFormat.getDefaultWireFormat():
            # This is the default wire encoding.  In the Blob constructor, set
            #   copy true, but if input is already a Blob, it won't copy.
            self._setDefaultWireEncoding(
                SignedBlob(Blob(input, True), signedPortionBeginOffset,
                           signedPortionEndOffset),
                WireFormat.getDefaultWireFormat())
        else:
            self._setDefaultWireEncoding(SignedBlob(), None)

    def getName(self):
        """
        Get the data packet's name.
        
        :return: The name.
        :rtype: Name
        """
        return self._name.get()

    def getMetaInfo(self):
        """
        Get the data packet's meta info.
        
        :return: The meta info.
        :rtype: MetaInfo
        """
        return self._metaInfo.get()

    def getSignature(self):
        """
        Get the data packet's signature object.
        
        :return: The signature object.
        :rtype: a subclass of Signature such as Sha256WithRsaSignature
        """
        return self._signature.get()

    def getContent(self):
        """
        Get the data packet's content.
        
        :return: The content as a Blob, which isNull() if unspecified.
        :rtype: Blob
        """
        return self._content

    def getDefaultWireEncoding(self):
        """
        Return the default wire encoding, which was encoded with
        getDefaultWireEncodingFormat().
        
        :return: The default wire encoding, whose isNull() may be true if there
          is no default wire encoding.
        :rtype: SignedBlob
        """
        if self._getDefaultWireEncodingChangeCount != self.getChangeCount():
            # The values have changed, so the default wire encoding is
            # invalidated.
            self._defaultWireEncoding = SignedBlob()
            self._defaultWireEncodingFormat = None
            self._getDefaultWireEncodingChangeCount = self.getChangeCount()

        return self._defaultWireEncoding

    def getDefaultWireEncodingFormat(self):
        """
        Get the WireFormat which is used by getDefaultWireEncoding().
        
        :return: The WireFormat, which is only meaningful if the 
          getDefaultWireEncoding() is not isNull().
        :rtype: WireFormat
        """
        return self._defaultWireEncodingFormat

    def setName(self, name):
        """
        Set name to a copy of the given Name.
        
        :param Name name: The Name which is copied.
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._name.set(name if type(name) is Name else Name(name))
        self._changeCount += 1
        return self

    def setMetaInfo(self, metaInfo):
        """
        Set metaInfo to a copy of the given MetaInfo.
        
        :param MetaInfo metaInfo: The MetaInfo which is copied.
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._metaInfo.set(MetaInfo() if metaInfo ==
                           None else MetaInfo(metaInfo))
        self._changeCount += 1
        return self

    def setSignature(self, signature):
        """
        Set the signature to a copy of the given signature.
        
        :param signature: The signature object which is cloned.
        :type signature: a subclass of Signature such as Sha256WithRsaSignature
        :return: This Data so that you can chain calls to update values.
        :rtype: Data
        """
        self._signature.set(Sha256WithRsaSignature() if signature ==
                            None else signature.clone())
        self._changeCount += 1
        return self

    def setContent(self, content):
        """
        Set the content to the given value.
        
        :param content: The array with the content bytes. If content is not a 
          Blob, then create a new Blob to copy the bytes (otherwise 
          take another pointer to the same Blob).
        :type content: A Blob or an array type with int elements 
        """
        self._content = content if type(content) is Blob else Blob(content)
        self._changeCount += 1

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object 
        (or a child object) is changed.
        
        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._name.checkChanged()
        changed = self._metaInfo.checkChanged() or changed
        changed = self._signature.checkChanged() or changed
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    def _setDefaultWireEncoding(self, defaultWireEncoding,
                                defaultWireEncodingFormat):
        self._defaultWireEncoding = defaultWireEncoding
        self._defaultWireEncodingFormat = defaultWireEncodingFormat
        # Set _getDefaultWireEncodingChangeCount so that the next call to
        # getDefaultWireEncoding() won't clear _defaultWireEncoding.
        self._getDefaultWireEncodingChangeCount = self.getChangeCount()
Ejemplo n.º 15
0
class KeyLocator(object):
    """
    Create a new KeyLocator object, possibly copying values from 
    another object.
    
    :param KeyLocator value: (optional) If value is a KeyLocator, copy its 
      values.  If value is omitted, set the fields to unspecified.
    """
    def __init__(self, value=None):
        if value == None:
            self._type = None
            self._keyName = ChangeCounter(Name())
            self._keyData = Blob()
        elif type(value) is KeyLocator:
            # Copy its values.
            self._type = value._type
            self._keyName = ChangeCounter(Name(value.getKeyName()))
            self._keyData = value._keyData
        else:
            raise RuntimeError(
                "Unrecognized type for KeyLocator constructor: " +
                repr(type(value)))

        self._changeCount = 0

    def getType(self):
        """
        Get the key locator type. If KeyLocatorType.KEYNAME, you may also
        getKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you may also
        getKeyData() to get the digest.
        
        :return: The key locator type, or None if not specified.
        :rtype: an int from KeyLocatorType
        """
        return self._type

    def getKeyName(self):
        """
        Get the key name.  This is meaningful if getType() is
        KeyLocatorType.KEYNAME.
        
        :return: The key name. If not specified, the Name is empty.
        :rtype: Name
        """
        return self._keyName.get()

    def getKeyData(self):
        """
        Get the key data.  This is the digest bytes if getType() is
        KeyLocatorType.KEY_LOCATOR_DIGEST.
        
        :return: The key data as a Blob, which isNull() if unspecified.
        :rtype: Blob
        """
        return self._keyData

    def setType(self, type):
        """
        Set the key locator type.  If KeyLocatorType.KEYNAME, you must also
        setKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you must also
        setKeyData() to set the digest.
        
        :param type: The key locator type.  If None, the type is unspecified.
        :type type: an int from KeyLocatorType
        """
        self._type = None if type == None or type < 0 else type
        self._changeCount += 1

    def setKeyName(self, keyName):
        """
        Set key name to a copy of the given Name.  This is the name if 
        getType() is KeyLocatorType.KEYNAME.
        
        :param Name keyName: The key name which is copied.
        """
        self._keyName.set(keyName if type(keyName) is Name else Name(keyName))
        self._changeCount += 1

    def setKeyData(self, keyData):
        """
        Set the key data to the given value.  This is the digest bytes if 
        getType() is KeyLocatorType.KEY_LOCATOR_DIGEST.
        
        :param keyData: The array with the key data bytes. If keyData is not a 
          Blob, then create a new Blob to copy the bytes (otherwise 
          take another pointer to the same Blob).
        :type keyData: A Blob or an array type with int elements 
        """
        self._keyData = keyData if type(keyData) is Blob else Blob(keyData)
        self._changeCount += 1

    def clear(self):
        """
        Clear the fields and set the type to None.
        """
        self._type = None
        self._keyName.get().clear()
        self._keyData = Blob()
        self._changeCount += 1

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object 
        (or a child object) is changed.
        
        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._keyName.checkChanged()
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount
Ejemplo n.º 16
0
class KeyLocator(object):
    """
    Create a new KeyLocator object, possibly copying values from
    another object.

    :param KeyLocator value: (optional) If value is a KeyLocator, copy its
      values.  If value is omitted, set the fields to unspecified.
    """
    def __init__(self, value = None):
        if value == None:
            self._type = None
            self._keyName = ChangeCounter(Name())
            self._keyData = Blob()
        elif type(value) is KeyLocator:
            # Copy its values.
            self._type = value._type
            self._keyName = ChangeCounter(Name(value.getKeyName()))
            self._keyData = value._keyData
        else:
            raise RuntimeError(
              "Unrecognized type for KeyLocator constructor: " +
              str(type(value)))

        self._changeCount = 0

    def getType(self):
        """
        Get the key locator type. If KeyLocatorType.KEYNAME, you may also
        getKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you may also
        getKeyData() to get the digest.

        :return: The key locator type, or None if not specified.
        :rtype: an int from KeyLocatorType
        """
        return self._type

    def getKeyName(self):
        """
        Get the key name.  This is meaningful if getType() is
        KeyLocatorType.KEYNAME.

        :return: The key name. If not specified, the Name is empty.
        :rtype: Name
        """
        return self._keyName.get()

    def getKeyData(self):
        """
        Get the key data.  This is the digest bytes if getType() is
        KeyLocatorType.KEY_LOCATOR_DIGEST.

        :return: The key data as a Blob, which isNull() if unspecified.
        :rtype: Blob
        """
        return self._keyData

    def setType(self, type):
        """
        Set the key locator type.  If KeyLocatorType.KEYNAME, you must also
        setKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you must also
        setKeyData() to set the digest.

        :param type: The key locator type.  If None, the type is unspecified.
        :type type: an int from KeyLocatorType
        """
        self._type = None if type == None or type < 0 else type
        self._changeCount += 1

    def setKeyName(self, keyName):
        """
        Set key name to a copy of the given Name.  This is the name if
        getType() is KeyLocatorType.KEYNAME.

        :param Name keyName: The key name which is copied.
        """
        self._keyName.set(keyName if type(keyName) is Name else Name(keyName))
        self._changeCount += 1

    def setKeyData(self, keyData):
        """
        Set the key data to the given value.  This is the digest bytes if
        getType() is KeyLocatorType.KEY_LOCATOR_DIGEST.

        :param keyData: The array with the key data bytes. If keyData is not a
          Blob, then create a new Blob to copy the bytes (otherwise
          take another pointer to the same Blob).
        :type keyData: A Blob or an array type with int elements
        """
        self._keyData = keyData if type(keyData) is Blob else Blob(keyData)
        self._changeCount += 1

    def clear(self):
        """
        Clear the fields and set the type to None.
        """
        self._type = None
        self._keyName.get().clear()
        self._keyData = Blob()
        self._changeCount += 1

    @staticmethod
    def canGetFromSignature(signature):
        """
        If the signature is a type that has a KeyLocator (so that
        getFromSignature will succeed), return true.
        Note: This is a static method of KeyLocator instead of a method of
        Signature so that the Signature base class does not need to be overloaded
        with all the different kinds of information that various signature
        algorithms may use.

        :param Signature signature: An object of a subclass of Signature.
        :return: True if the signature is a type that has a KeyLocator,
          otherwise False.
        :rtype: bool
        """
        return type(signature) is Sha256WithRsaSignature

    @staticmethod
    def getFromSignature(signature):
        """
        If the signature is a type that has a KeyLocator, then return it. Otherwise
        throw an error.

        :param Signature signature: An object of a subclass of Signature.
        :return: The signature's KeyLocator. It is an error if signature doesn't
          have a KeyLocator.
        :rtype: KeyLocator
        """
        if type(signature) is Sha256WithRsaSignature:
            return signature.getKeyLocator()
        else:
            raise RuntimeError(
              "KeyLocator.getFromSignature: Signature type does not have a KeyLocator")

    def getChangeCount(self):
        """
        Get the change count, which is incremented each time this object
        (or a child object) is changed.

        :return: The change count.
        :rtype: int
        """
        # Make sure each of the checkChanged is called.
        changed = self._keyName.checkChanged()
        if changed:
            # A child object has changed, so update the change count.
            self._changeCount += 1

        return self._changeCount

    # Create managed properties for read/write properties of the class for more pythonic syntax.
    type = property(getType, setType)
    keyName = property(getKeyName, setKeyName)
    keyData = property(getKeyData, setKeyData)

    # Support property-based equivalence check
    # TODO: Desired syntax?
    def equals(self, other):
        if self is None and other is None: return True
        if other is None: return False
        if self._type != other._type: return False
        if self._keyName.get() != None and not self._keyName.get().equals(other._keyName.get()): return False
        if self._keyData != None and not self._keyData.equals(other._keyData): return False
        return True