Example #1
0
 def __init__(self, elementListener):
     self._elementListener = elementListener
     self._binaryXmlStructureDecoder = BinaryXmlStructureDecoder()
     self._tlvStructureDecoder = TlvStructureDecoder()
     self._usePartialData = False
     self._partialData = DynamicByteArray(1000)
     self._useTlv = None
 def __init__(self):
     self._gotElementEnd = False
     self._offset = 0
     self._level = 0
     self._state = self.READ_HEADER_OR_CLOSE
     self._headerLength = 0
     self._useHeaderBuffer = False
     # 10 bytes is enough to hold an encoded header with a type and a 64 bit value.
     self._headerBuffer = DynamicByteArray(10)
     self._nBytesToRead = 0
Example #3
0
 def __init__(self, elementListener):
     self._elementListener = elementListener
     self._binaryXmlStructureDecoder = BinaryXmlStructureDecoder()
     self._tlvStructureDecoder = TlvStructureDecoder()
     self._usePartialData = False
     self._partialData = DynamicByteArray(1000)
     self._useTlv = None
Example #4
0
class ElementReader(object):
    """
    Create an ElementReader with the elementListener and an initial buffer for
    saving partial data.
    """
    def __init__(self, elementListener):
        self._elementListener = elementListener
        self._tlvStructureDecoder = TlvStructureDecoder()
        self._usePartialData = False
        self._partialData = DynamicByteArray(1000)
        self._partialDataLength = 0

    def onReceivedData(self, data):
        """
        Continue to read data until the end of an element, then call
        elementListener.onReceivedElement(element). The buffer passed to
        onReceivedElement is only valid during this call.  If you need the data
        later, you must copy.

        :param data: The buffer with the incoming element's bytes.
        :type data: An array type with int elements
        """
        # Create a Blob and take its buf() since this creates a memoryview
        #   which is more efficient for slicing.
        data = Blob(data, False).buf()

        # Process multiple objects in the data.
        while True:
            try:
                if not self._usePartialData:
                    # This is the beginning of an element.
                    if len(data) <= 0:
                        # Wait for more data.
                        return

                # Scan the input to check if a whole TLV element has been read.
                self._tlvStructureDecoder.seek(0)
                gotElementEnd = self._tlvStructureDecoder.findElementEnd(data)
                offset = self._tlvStructureDecoder.getOffset()
            except ValueError as ex:
                # Reset to read a new element on the next call.
                self._usePartialData = False
                self._tlvStructureDecoder = TlvStructureDecoder()

                raise ex

            if gotElementEnd:
                # Got the remainder of an element. Report to the caller.
                if self._usePartialData:
                    # We have partial data from a previous call, so append this
                    #   data and use partialData for onReceivedElement.
                    self._partialData.copy(
                      data[:offset], self._partialDataLength)
                    self._partialDataLength += offset

                    # Create a Blob and take its buf() since this creates a
                    #   memoryview which is more efficient for slicing.
                    partialDataView = Blob(
                      self._partialData.getArray(), False).buf()
                    element = partialDataView[:self._partialDataLength]
                    # Assume we don't need to use partialData anymore until
                    #   needed.
                    self._usePartialData = False
                else:
                    # We are not using partialData, so just point to the input
                    #   data buffer.
                    element = data[:offset]

                # Reset to read a new object. Do this before calling
                # onReceivedElement in case it throws an exception.
                data = data[offset:]
                self._tlvStructureDecoder = TlvStructureDecoder()

                self._elementListener.onReceivedElement(element)
                if len(data) == 0:
                    # No more data in the packet.
                    return

                # else loop back to decode.
            else:
                # Save remaining data for a later call.
                if not self._usePartialData:
                    self._usePartialData = True
                    self._partialDataLength = 0

                if self._partialDataLength + len(data) > Common.MAX_NDN_PACKET_SIZE:
                    # Reset to read a new element on the next call.
                    self._usePartialData = False
                    self._tlvStructureDecoder = TlvStructureDecoder()

                    raise ValueError(
                      "The incoming packet exceeds the maximum limit Face.getMaxNdnPacketSize()")

                self._partialData.copy(data, self._partialDataLength)
                self._partialDataLength += len(data)

                return
Example #5
0
class ElementReader(object):
    """
    Create an ElementReader with the elementListener and an initial buffer for
    saving partial data.
    """
    def __init__(self, elementListener):
        self._elementListener = elementListener
        self._tlvStructureDecoder = TlvStructureDecoder()
        self._usePartialData = False
        self._partialData = DynamicByteArray(1000)
        self._partialDataLength = 0

    def onReceivedData(self, data):
        """
        Continue to read data until the end of an element, then call
        elementListener.onReceivedElement(element). The buffer passed to
        onReceivedElement is only valid during this call.  If you need the data
        later, you must copy.

        :param data: The buffer with the incoming element's bytes.
        :type data: An array type with int elements
        """
        # Create a Blob and take its buf() since this creates a memoryview
        #   which is more efficient for slicing.
        data = Blob(data, False).buf()

        # Process multiple objects in the data.
        while True:
            try:
                if not self._usePartialData:
                    # This is the beginning of an element.
                    if len(data) <= 0:
                        # Wait for more data.
                        return

                # Scan the input to check if a whole TLV element has been read.
                self._tlvStructureDecoder.seek(0)
                gotElementEnd = self._tlvStructureDecoder.findElementEnd(data)
                offset = self._tlvStructureDecoder.getOffset()
            except ValueError as ex:
                # Reset to read a new element on the next call.
                self._usePartialData = False
                self._tlvStructureDecoder = TlvStructureDecoder()

                raise ex

            if gotElementEnd:
                # Got the remainder of an element. Report to the caller.
                if self._usePartialData:
                    # We have partial data from a previous call, so append this
                    #   data and use partialData for onReceivedElement.
                    self._partialData.copy(
                      data[:offset], self._partialDataLength)
                    self._partialDataLength += offset

                    # Create a Blob and take its buf() since this creates a
                    #   memoryview which is more efficient for slicing.
                    partialDataView = Blob(
                      self._partialData.getArray(), False).buf()
                    element = partialDataView[:self._partialDataLength]
                    # Assume we don't need to use partialData anymore until
                    #   needed.
                    self._usePartialData = False
                else:
                    # We are not using partialData, so just point to the input
                    #   data buffer.
                    element = data[:offset]

                # Reset to read a new object. Do this before calling
                # onReceivedElement in case it throws an exception.
                data = data[offset:]
                self._tlvStructureDecoder = TlvStructureDecoder()

                self._elementListener.onReceivedElement(element)
                if len(data) == 0:
                    # No more data in the packet.
                    return

                # else loop back to decode.
            else:
                # Save remaining data for a later call.
                if not self._usePartialData:
                    self._usePartialData = True
                    self._partialDataLength = 0

                if self._partialDataLength + len(data) > Common.MAX_NDN_PACKET_SIZE:
                    # Reset to read a new element on the next call.
                    self._usePartialData = False
                    self._tlvStructureDecoder = TlvStructureDecoder()

                    raise ValueError(
                      "The incoming packet exceeds the maximum limit Face.getMaxNdnPacketSize()")

                self._partialData.copy(data, self._partialDataLength)
                self._partialDataLength += len(data)

                return
Example #6
0
 def __init__(self, initialCapacity = 16):
     self._output = DynamicByteArray(initialCapacity)
     # _length is the number of bytes that have been written to the back of 
     #   self._output._array.
     self._length = 0
Example #7
0
class TlvEncoder(object):
    """
    Create a new TlvEncoder with an initialCapacity for the encoding buffer.
    
    :param int initialCapacity: (optional) The initial capacity of the encoding 
      buffer. If omitted, use a default value.
    """
    def __init__(self, initialCapacity = 16):
        self._output = DynamicByteArray(initialCapacity)
        # _length is the number of bytes that have been written to the back of 
        #   self._output._array.
        self._length = 0
        
    def __len__(self):
        """
        Get the number of bytes that have been written to the output.  You can
        save this number, write sub TLVs, then subtract the new len from this
        to get the total length of the sub TLVs.
        
        :return: The number of bytes that have been written to the output.
        :rtype: int
        """
        return self._length        
        
    def writeVarNumber(self, varNumber):
        """
        Encode varNumber as a VAR-NUMBER in NDN-TLV and write it to 
        self._output just before self._length from the back.  
        Advance self._length.
        
        :param int varNumber: The non-negative number to encode.
        """
        if varNumber < 253:
            self._length += 1
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = varNumber & 0xff
        elif varNumber <= 0xffff:
            self._length += 3
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = 253
            self._output._array[-self._length + 1] = (varNumber >> 8) & 0xff
            self._output._array[-self._length + 2] = varNumber & 0xff
        elif varNumber <= 0xffffffff:
            self._length += 5
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = 254
            self._output._array[-self._length + 1] = (varNumber >> 24) & 0xff
            self._output._array[-self._length + 2] = (varNumber >> 16) & 0xff
            self._output._array[-self._length + 3] = (varNumber >> 8) & 0xff
            self._output._array[-self._length + 4] = varNumber & 0xff
        else:
            self._length += 9
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = 255
            self._output._array[-self._length + 1] = (varNumber >> 56) & 0xff
            self._output._array[-self._length + 2] = (varNumber >> 48) & 0xff
            self._output._array[-self._length + 3] = (varNumber >> 40) & 0xff
            self._output._array[-self._length + 4] = (varNumber >> 32) & 0xff
            self._output._array[-self._length + 5] = (varNumber >> 24) & 0xff
            self._output._array[-self._length + 6] = (varNumber >> 16) & 0xff
            self._output._array[-self._length + 7] = (varNumber >> 8) & 0xff
            self._output._array[-self._length + 8] = varNumber & 0xff

    def writeTypeAndLength(self, type, length):
        """
        Encode the type and length as VAR-NUMBER and write to 
        self._output just before self._length from the back.  
        Advance self._length.
        
        :param int type: The type of the TLV.
        :param int length: The non-negative length of the TLV.
        """
        # Write backwards.
        self.writeVarNumber(length)
        self.writeVarNumber(type)
            
    def writeNonNegativeInteger(self, value):
        """
        Encode value as a non-negative integer and write it to self._output 
        just before self._length from the back. Advance self._length.
 
        :param int value: The non-negative integer to encode.
        """
        if value < 0:
            raise ValueError("TLV integer value may not be negative")
        
        if value <= 0xff:
            self._length += 1
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = value & 0xff
        elif value <= 0xffff:
            self._length += 2
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length]     = (value >> 8) & 0xff
            self._output._array[-self._length + 1] = value & 0xff
        elif value <= 0xffffffff:
            self._length += 4
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length]     = (value >> 24) & 0xff
            self._output._array[-self._length + 1] = (value >> 16) & 0xff
            self._output._array[-self._length + 2] = (value >> 8) & 0xff
            self._output._array[-self._length + 3] = value & 0xff
        else:
            self._length += 8
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length]     = (value >> 56) & 0xff
            self._output._array[-self._length + 1] = (value >> 48) & 0xff
            self._output._array[-self._length + 2] = (value >> 40) & 0xff
            self._output._array[-self._length + 3] = (value >> 32) & 0xff
            self._output._array[-self._length + 4] = (value >> 24) & 0xff
            self._output._array[-self._length + 5] = (value >> 16) & 0xff
            self._output._array[-self._length + 6] = (value >> 8) & 0xff
            self._output._array[-self._length + 7] = value & 0xff

    def writeNonNegativeIntegerTlv(self, type, value):
        """
        Write the type, then the length of the encoded value then encode value 
        as a non-negative integer and write it to self._output just before 
        self._length from the back. Advance self._length.
 
        :param int type: The type of the TLV.
        :param int value: The non-negative integer to encode.
        """
        # Write backwards.
        saveNBytes = self._length
        self.writeNonNegativeInteger(value)
        self.writeTypeAndLength(type, self._length - saveNBytes)

    def writeOptionalNonNegativeIntegerTlv(self, type, value):
        """
        If value is negative or None then do nothing, otherwise call 
        writeNonNegativeIntegerTlv.
 
        :param int type: The type of the TLV.
        :param int value: If negative or None do nothing, otherwise the integer 
          to encode.
        """
        if value != None and value >= 0:
            self.writeNonNegativeIntegerTlv(type, value)

    def writeOptionalNonNegativeIntegerTlvFromFloat(self, type, value):
        """
        If value is negative or None then do nothing, otherwise call 
        writeNonNegativeIntegerTlv.
 
        :param int type: The type of the TLV.
        :param float value: If negative or None do nothing, otherwise use 
          int(round(value)).
        """
        if value != None and value >= 0:
            # Note: int() will return int, or long if value is large and this 
            #   is a 32-bit system.
            self.writeNonNegativeIntegerTlv(type, int(round(value)))

    def writeBlobTlv(self, type, value):
        """
        Write the type, then the length of the blob then the blob value 
        to self._output just before self._length from the back. 
        Advance self._length.
        
        :param int type: The type of the TLV.
        :param value: The byte array with the bytes of the blob.  If value is
          None, then just write the type and length 0.
        :type value: bytearray or memoryview
        """
        if value == None:
            self.writeTypeAndLength(type, 0)
            return
            
        # Write backwards, starting with the blob array.        
        self._length += len(value)
        self._output.copyFromBack(value, self._length)
        
        self.writeTypeAndLength(type, len(value))

    def writeOptionalBlobTlv(self, type, value):
        """
        If the byte array is None or zero length then do nothing, otherwise
        call writeBlobTlv.
        
        :param int type: The type of the TLV.
        :param value: If None or zero length do nothing, otherwise the byte 
          array with the bytes of the blob.
        :type value: bytearray or memoryview
        """
        if value != None and len(value) > 0:
            self.writeBlobTlv(type, value)
        
    def getOutput(self):
        """
        Get a memoryview slice of the encoded bytes.
        
        :return: a memoryview backed by the bytearray encoding buffer.
        :rtype: memoryview
        """
        # Create a memoryview from getArray() to make sure we don't copy.
        return memoryview(
         self._output.getArray())[len(self._output.getArray()) - self._length:]
class BinaryXmlStructureDecoder(object):
    """
    Create and initialize a BinaryXmlStructureDecoder.
    """
    def __init__(self):
        self._gotElementEnd = False
        self._offset = 0
        self._level = 0
        self._state = self.READ_HEADER_OR_CLOSE
        self._headerLength = 0
        self._useHeaderBuffer = False
        # 10 bytes is enough to hold an encoded header with a type and a 64 bit value.
        self._headerBuffer = DynamicByteArray(10)
        self._nBytesToRead = 0

    READ_HEADER_OR_CLOSE = 0
    READ_BYTES = 1
    
    def findElementEnd(self, input):
        """
        Continue scanning input starting from self._offset to find the element 
        end.  If the end of the element which started at offset 0 is found, 
        this returns True and getOffset() is the length of the element.  
        Otherwise, this returns False which means you should read more into 
        input and call again.
        
        :param input: The input buffer. You have to pass in input each time 
          because the buffer could be reallocated.
        :type input: An array type with int elements
        :return: True if found the element end, False if not.
        :rtype: bool
        """
        if self._gotElementEnd:
            # Someone is calling when we already got the end.
            return True

        decoder = BinaryXmlDecoder(input)

        while True:
            if self._offset >= len(input):
                # All the cases assume we have some input.
                return False

            if self._state == BinaryXmlStructureDecoder.READ_HEADER_OR_CLOSE:                             
                # First check for CLOSE.
                if (self._headerLength == 0 and 
                    input[self._offset] == BinaryXmlDecoder.CLOSE):
                    self._offset += 1
                    # Close the level.
                    self._level -= 1
                    if self._level == 0:
                        # Finished.
                        self._gotElementEnd = True
                        return True

                    if self._level < 0:
                        raise RuntimeError(
                  "BinaryXmlStructureDecoder: Unexpected close tag at offset " + 
                          repr(self._offset - 1))

                    # Get ready for the next header.
                    self._startHeader()
                    continue

                startingHeaderLength = self._headerLength
                while True:
                    if self._offset >= len(input):
                        # We can't get all of the header bytes from this input. 
                        # Save in headerBuffer.
                        self._useHeaderBuffer = True
                        nNewBytes = self._headerLength - startingHeaderLength
                        self._headerBuffer.copy(
                          input[self._offset - nNewBytes:self._offset], 
                          startingHeaderLength)

                        return False

                    headerByte = input[self._offset]
                    self._offset += 1
                    self._headerLength += 1
                    if headerByte & BinaryXmlDecoder.TT_FINAL:
                        # Break and read the header.
                        break

                if self._useHeaderBuffer:
                    # Copy the remaining bytes into headerBuffer.
                    nNewBytes = self._headerLength - startingHeaderLength
                    self._headerBuffer.copy(
                      input[self._offset - nNewBytes:self._offset], 
                      startingHeaderLength)

                    (type, value) = BinaryXmlDecoder(
                      self._headerBuffer.getArray()).decodeTypeAndValue()
                else:
                    # We didn't have to use the headerBuffer.
                    decoder.seek(self._offset - self._headerLength)
                    (type, value) = decoder.decodeTypeAndValue()

                # Set the next state based on the type.
                if type == BinaryXmlDecoder.DATTR:
                    # We already consumed the item. READ_HEADER_OR_CLOSE again.
                    # ndnb has rules about what must follow an attribute, but we 
                    # are just scanning.
                    self._startHeader()
                elif (type == BinaryXmlDecoder.DTAG or 
                      type == BinaryXmlDecoder.EXT):
                    # Start a new level and READ_HEADER_OR_CLOSE again.
                    self._level += 1
                    self._startHeader()
                elif (type == BinaryXmlDecoder.TAG or 
                      type == BinaryXmlDecoder.ATTR):
                    if type == BinaryXmlDecoder.TAG:
                        # Start a new level and read the tag.
                        self._level += 1
                    # Minimum tag or attribute length is 1.
                    self._nBytesToRead = value + 1
                    self._state = BinaryXmlStructureDecoder.READ_BYTES
                    # ndnb has rules about what must follow an attribute, but we 
                    # are just scanning.
                elif (type == BinaryXmlDecoder.BLOB or
                      type == BinaryXmlDecoder.UDATA):
                    self._nBytesToRead = value
                    self._state = BinaryXmlStructureDecoder.READ_BYTES
                else:
                    raise RuntimeError(
                      "BinaryXmlStructureDecoder: Unrecognized header type " + 
                      repr(type))
            elif self._state == BinaryXmlStructureDecoder.READ_BYTES:
                nRemainingBytes = len(input) - self._offset
                if nRemainingBytes < self._nBytesToRead:
                    # Need more.
                    self._offset += nRemainingBytes
                    self._nBytesToRead -= nRemainingBytes
                    return False

                # Got the bytes. Read a new header or close.
                self._offset += self._nBytesToRead
                self._startHeader()
            else:
                # We don't expect this to happen.
                raise RuntimeError(
                  "BinaryXmlStructureDecoder: Unrecognized state " + 
                  repr(self._state))
    
    def getOffset(self):
        """
        Get the current offset into the input buffer.
        
        :return: The offset.
        :rtype: int
        """
        return self._offset
    
    def seek(self, offset):
        """
        Set the offset into the input, used for the next read.
        
        :param int offset: The new offset.
        """
        self._offset = offset
        
    def _startHeader(self):
        """
        A private method to set the state to READ_HEADER_OR_CLOSE and set up to 
        start reading the header.
        """
        self._headerLength = 0
        self._useHeaderBuffer = False
        self._state = BinaryXmlStructureDecoder.READ_HEADER_OR_CLOSE
        
Example #9
0
 def __init__(self, initialCapacity=16):
     self._output = DynamicByteArray(initialCapacity)
     # _length is the number of bytes that have been written to the back of
     #   self._output._array.
     self._length = 0
Example #10
0
class TlvEncoder(object):
    """
    Create a new TlvEncoder with an initialCapacity for the encoding buffer.

    :param int initialCapacity: (optional) The initial capacity of the encoding
      buffer. If omitted, use a default value.
    """
    def __init__(self, initialCapacity=16):
        self._output = DynamicByteArray(initialCapacity)
        # _length is the number of bytes that have been written to the back of
        #   self._output._array.
        self._length = 0

    def __len__(self):
        """
        Get the number of bytes that have been written to the output.  You can
        save this number, write sub TLVs, then subtract the new len from this
        to get the total length of the sub TLVs.

        :return: The number of bytes that have been written to the output.
        :rtype: int
        """
        return self._length

    def writeVarNumber(self, varNumber):
        """
        Encode varNumber as a VAR-NUMBER in NDN-TLV and write it to
        self._output just before self._length from the back.
        Advance self._length.

        :param int varNumber: The non-negative number to encode.
        """
        if varNumber < 253:
            self._length += 1
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = varNumber & 0xff
        elif varNumber <= 0xffff:
            self._length += 3
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = 253
            self._output._array[-self._length + 1] = (varNumber >> 8) & 0xff
            self._output._array[-self._length + 2] = varNumber & 0xff
        elif varNumber <= 0xffffffff:
            self._length += 5
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = 254
            self._output._array[-self._length + 1] = (varNumber >> 24) & 0xff
            self._output._array[-self._length + 2] = (varNumber >> 16) & 0xff
            self._output._array[-self._length + 3] = (varNumber >> 8) & 0xff
            self._output._array[-self._length + 4] = varNumber & 0xff
        else:
            self._length += 9
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = 255
            self._output._array[-self._length + 1] = (varNumber >> 56) & 0xff
            self._output._array[-self._length + 2] = (varNumber >> 48) & 0xff
            self._output._array[-self._length + 3] = (varNumber >> 40) & 0xff
            self._output._array[-self._length + 4] = (varNumber >> 32) & 0xff
            self._output._array[-self._length + 5] = (varNumber >> 24) & 0xff
            self._output._array[-self._length + 6] = (varNumber >> 16) & 0xff
            self._output._array[-self._length + 7] = (varNumber >> 8) & 0xff
            self._output._array[-self._length + 8] = varNumber & 0xff

    def writeTypeAndLength(self, type, length):
        """
        Encode the type and length as VAR-NUMBER and write to
        self._output just before self._length from the back.
        Advance self._length.

        :param int type: The type of the TLV.
        :param int length: The non-negative length of the TLV.
        """
        # Write backwards.
        self.writeVarNumber(length)
        self.writeVarNumber(type)

    def writeNonNegativeInteger(self, value):
        """
        Encode value as a non-negative integer and write it to self._output
        just before self._length from the back. Advance self._length.

        :param int value: The non-negative integer to encode.
        """
        if value < 0:
            raise ValueError("TLV integer value may not be negative")

        if value <= 0xff:
            self._length += 1
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = value & 0xff
        elif value <= 0xffff:
            self._length += 2
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = (value >> 8) & 0xff
            self._output._array[-self._length + 1] = value & 0xff
        elif value <= 0xffffffff:
            self._length += 4
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = (value >> 24) & 0xff
            self._output._array[-self._length + 1] = (value >> 16) & 0xff
            self._output._array[-self._length + 2] = (value >> 8) & 0xff
            self._output._array[-self._length + 3] = value & 0xff
        else:
            self._length += 8
            self._output.ensureLengthFromBack(self._length)
            self._output._array[-self._length] = (value >> 56) & 0xff
            self._output._array[-self._length + 1] = (value >> 48) & 0xff
            self._output._array[-self._length + 2] = (value >> 40) & 0xff
            self._output._array[-self._length + 3] = (value >> 32) & 0xff
            self._output._array[-self._length + 4] = (value >> 24) & 0xff
            self._output._array[-self._length + 5] = (value >> 16) & 0xff
            self._output._array[-self._length + 6] = (value >> 8) & 0xff
            self._output._array[-self._length + 7] = value & 0xff

    def writeNonNegativeIntegerTlv(self, type, value):
        """
        Write the type, then the length of the encoded value then encode value
        as a non-negative integer and write it to self._output just before
        self._length from the back. Advance self._length.

        :param int type: The type of the TLV.
        :param int value: The non-negative integer to encode.
        """
        # Write backwards.
        saveNBytes = self._length
        self.writeNonNegativeInteger(value)
        self.writeTypeAndLength(type, self._length - saveNBytes)

    def writeOptionalNonNegativeIntegerTlv(self, type, value):
        """
        If value is negative or None then do nothing, otherwise call
        writeNonNegativeIntegerTlv.

        :param int type: The type of the TLV.
        :param int value: If negative or None do nothing, otherwise the integer
          to encode.
        """
        if value != None and value >= 0:
            self.writeNonNegativeIntegerTlv(type, value)

    def writeOptionalNonNegativeIntegerTlvFromFloat(self, type, value):
        """
        If value is negative or None then do nothing, otherwise call
        writeNonNegativeIntegerTlv.

        :param int type: The type of the TLV.
        :param float value: If negative or None do nothing, otherwise use
          int(round(value)).
        """
        if value != None and value >= 0:
            # Note: int() will return int, or long if value is large and this
            #   is a 32-bit system.
            self.writeNonNegativeIntegerTlv(type, int(round(value)))

    def writeBuffer(self, buffer):
        """
        Write the buffer value to self._output just before self._length from the
        back. Advance self._length.

        :param buffer: The byte array with the bytes to write. If value is None,
          then do nothing.
        :type value: bytearray or memoryview
        """
        if buffer == None:
            return

        self._length += len(buffer)
        self._output.copyFromBack(buffer, self._length)

    def writeBlobTlv(self, type, value):
        """
        Write the type, then the length of the blob then the blob value
        to self._output just before self._length from the back.
        Advance self._length.

        :param int type: The type of the TLV.
        :param value: The byte array with the bytes of the blob.  If value is
          None, then just write the type and length 0.
        :type value: bytearray or memoryview
        """
        if value == None:
            self.writeTypeAndLength(type, 0)
            return

        # Write backwards, starting with the blob array.
        self.writeBuffer(value)
        self.writeTypeAndLength(type, len(value))

    def writeOptionalBlobTlv(self, type, value):
        """
        If the byte array is None or zero length then do nothing, otherwise
        call writeBlobTlv.

        :param int type: The type of the TLV.
        :param value: If None or zero length do nothing, otherwise the byte
          array with the bytes of the blob.
        :type value: bytearray or memoryview
        """
        if value != None and len(value) > 0:
            self.writeBlobTlv(type, value)

    def getOutput(self):
        """
        Get a memoryview slice of the encoded bytes.

        :return: a memoryview backed by the bytearray encoding buffer.
        :rtype: memoryview
        """
        # Create a memoryview from getArray() to make sure we don't copy.
        return memoryview(
            self._output.getArray())[len(self._output.getArray()) -
                                     self._length:]
Example #11
0
class ElementReader(object):
    """
    Create an ElementReader with the elementListener and an initial buffer for 
    saving partial data.
    """
    def __init__(self, elementListener):
        self._elementListener = elementListener
        self._binaryXmlStructureDecoder = BinaryXmlStructureDecoder()
        self._tlvStructureDecoder = TlvStructureDecoder()
        self._usePartialData = False
        self._partialData = DynamicByteArray(1000)
        self._useTlv = None

    def onReceivedData(self, data):
        """
        Continue to read data until the end of an element, then call 
        elementListener.onReceivedElement(element). The buffer passed to 
        onReceivedElement is only valid during this call.  If you need the data 
        later, you must copy.
 
        :param data: The buffer with the incoming element's bytes.
        :type data: An array type with int elements
        """
        # Create a Blob and take its buf() since this creates a memoryview
        #   which is more efficient for slicing.
        data = Blob(data, False).buf()

        # Process multiple objects in the data.
        while True:
            if not self._usePartialData:
                # This is the beginning of an element. Check whether it is 
                #  Binary XML or TLV.
                if len(data) <= 0:
                    # Wait for more data.
                    return

                # The type codes for TLV Interest and Data packets are chosen to not
                #   conflict with the first byte of a binary XML packet, so we can
                #   just look at the first byte.
                if (data[0] == Tlv.Interest or data[0] == Tlv.Data or 
                    data[0] == 0x80):
                    self._useTlv = True
                else:
                    # Binary XML.
                    self._useTlv = False

            if self._useTlv:
                # Scan the input to check if a whole TLV element has been read.
                self._tlvStructureDecoder.seek(0)    
                gotElementEnd = self._tlvStructureDecoder.findElementEnd(data)
                offset = self._tlvStructureDecoder.getOffset()
            else:
                # Scan the input to check if a whole Binary XML element has been 
                #   read.
                self._binaryXmlStructureDecoder.seek(0)    
                gotElementEnd = self._binaryXmlStructureDecoder.findElementEnd(data)
                offset = self._binaryXmlStructureDecoder.getOffset()
            
            if gotElementEnd:
                # Got the remainder of an element. Report to the caller.
                if self._usePartialData:
                    # We have partial data from a previous call, so append this 
                    #   data and use partialData for onReceivedElement.
                    self._partialData.copy(
                      data[:offset], self._partialDataLength)
                    self._partialDataLength += offset

                    # Create a Blob and take its buf() since this creates a 
                    #   memoryview which is more efficient for slicing.
                    partialDataView = Blob(
                      self._partialData.getArray(), False).buf()
                    self._elementListener.onReceivedElement(
                      partialDataView[:self._partialDataLength])
                    # Assume we don't need to use partialData anymore until 
                    #   needed.
                    self._usePartialData = False
                else:
                    # We are not using partialData, so just point to the input 
                    #   data buffer.
                    self._elementListener.onReceivedElement(data[:offset])

                # Need to read a new object.
                data = data[offset:]
                self._binaryXmlStructureDecoder = BinaryXmlStructureDecoder()
                self._tlvStructureDecoder = TlvStructureDecoder()
                if len(data) == 0:
                    # No more data in the packet.
                    return

                # else loop back to decode.
            else:
                # Save remaining data for a later call.
                if not self._usePartialData:
                    self._usePartialData = True
                    self._partialDataLength = 0

                self._partialData.copy(data, self._partialDataLength)
                self._partialDataLength += len(data)

                return
Example #12
0
class ElementReader(object):
    """
    Create an ElementReader with the elementListener and an initial buffer for 
    saving partial data.
    """
    def __init__(self, elementListener):
        self._elementListener = elementListener
        self._binaryXmlStructureDecoder = BinaryXmlStructureDecoder()
        self._tlvStructureDecoder = TlvStructureDecoder()
        self._usePartialData = False
        self._partialData = DynamicByteArray(1000)
        self._useTlv = None

    def onReceivedData(self, data):
        """
        Continue to read data until the end of an element, then call 
        elementListener.onReceivedElement(element). The buffer passed to 
        onReceivedElement is only valid during this call.  If you need the data 
        later, you must copy.
 
        :param data: The buffer with the incoming element's bytes.
        :type data: An array type with int elements
        """
        # Create a Blob and take its buf() since this creates a memoryview
        #   which is more efficient for slicing.
        data = Blob(data, False).buf()

        # Process multiple objects in the data.
        while True:
            if not self._usePartialData:
                # This is the beginning of an element. Check whether it is
                #  Binary XML or TLV.
                if len(data) <= 0:
                    # Wait for more data.
                    return

                # The type codes for TLV Interest and Data packets are chosen to not
                #   conflict with the first byte of a binary XML packet, so we can
                #   just look at the first byte.
                if (data[0] == Tlv.Interest or data[0] == Tlv.Data
                        or data[0] == 0x80):
                    self._useTlv = True
                else:
                    # Binary XML.
                    self._useTlv = False

            if self._useTlv:
                # Scan the input to check if a whole TLV element has been read.
                self._tlvStructureDecoder.seek(0)
                gotElementEnd = self._tlvStructureDecoder.findElementEnd(data)
                offset = self._tlvStructureDecoder.getOffset()
            else:
                # Scan the input to check if a whole Binary XML element has been
                #   read.
                self._binaryXmlStructureDecoder.seek(0)
                gotElementEnd = self._binaryXmlStructureDecoder.findElementEnd(
                    data)
                offset = self._binaryXmlStructureDecoder.getOffset()

            if gotElementEnd:
                # Got the remainder of an element. Report to the caller.
                if self._usePartialData:
                    # We have partial data from a previous call, so append this
                    #   data and use partialData for onReceivedElement.
                    self._partialData.copy(data[:offset],
                                           self._partialDataLength)
                    self._partialDataLength += offset

                    # Create a Blob and take its buf() since this creates a
                    #   memoryview which is more efficient for slicing.
                    partialDataView = Blob(self._partialData.getArray(),
                                           False).buf()
                    self._elementListener.onReceivedElement(
                        partialDataView[:self._partialDataLength])
                    # Assume we don't need to use partialData anymore until
                    #   needed.
                    self._usePartialData = False
                else:
                    # We are not using partialData, so just point to the input
                    #   data buffer.
                    self._elementListener.onReceivedElement(data[:offset])

                # Need to read a new object.
                data = data[offset:]
                self._binaryXmlStructureDecoder = BinaryXmlStructureDecoder()
                self._tlvStructureDecoder = TlvStructureDecoder()
                if len(data) == 0:
                    # No more data in the packet.
                    return

                # else loop back to decode.
            else:
                # Save remaining data for a later call.
                if not self._usePartialData:
                    self._usePartialData = True
                    self._partialDataLength = 0

                self._partialData.copy(data, self._partialDataLength)
                self._partialDataLength += len(data)

                return