Exemple #1
0
  def test_equality(self):
    # LinkProtocols should be comparable with both other LinkProtocols and
    # integers.

    protocol = LinkProtocol(1)

    self.assertEqual(LinkProtocol(1), protocol)
    self.assertNotEqual(LinkProtocol(2), protocol)

    self.assertEqual(1, protocol)
    self.assertNotEqual(2, protocol)
Exemple #2
0
  def test_attributes(self):
    protocol = LinkProtocol(1)
    self.assertEqual(1, protocol.version)
    self.assertEqual(Size.SHORT, protocol.circ_id_size)
    self.assertEqual(512, protocol.fixed_cell_length)
    self.assertEqual(0x01, protocol.first_circ_id)

    protocol = LinkProtocol(10)
    self.assertEqual(10, protocol.version)
    self.assertEqual(Size.LONG, protocol.circ_id_size)
    self.assertEqual(514, protocol.fixed_cell_length)
    self.assertEqual(0x80000000, protocol.first_circ_id)
Exemple #3
0
    def pop(
        content: bytes, link_protocol: 'stem.client.datatype.LinkProtocol'
    ) -> Tuple['stem.client.cell.Cell', bytes]:
        """
    Unpacks the first cell.

    :param content: payload to decode
    :param link_protocol: link protocol version

    :returns: (:class:`~stem.client.cell.Cell`, remainder) tuple

    :raises:
      * ValueError if content is malformed
      * NotImplementedError if unable to unpack this cell type
    """

        link_protocol = LinkProtocol(link_protocol)

        circ_id, content = link_protocol.circ_id_size.pop(content)
        command, content = CELL_TYPE_SIZE.pop(content)
        cls = Cell.by_value(command)

        if cls.IS_FIXED_SIZE:
            payload_len = FIXED_PAYLOAD_LEN
        else:
            payload_len, content = PAYLOAD_LEN_SIZE.pop(content)

        if len(content) < payload_len:
            raise ValueError(
                '%s cell should have a payload of %i bytes, but only had %i' %
                (cls.NAME, payload_len, len(content)))

        payload, content = split(content, payload_len)
        return cls._unpack(payload, circ_id, link_protocol), content
Exemple #4
0
 def __init__(self, orport: stem.socket.RelaySocket,
              link_protocol: int) -> None:
     self.link_protocol = LinkProtocol(link_protocol)
     self._orport = orport
     self._orport_buffer = b''  # unread bytes
     self._orport_lock = threading.RLock()
     self._circuits = {}  # type: Dict[int, stem.client.Circuit]
Exemple #5
0
  def test_use_as_int(self):
    protocol = LinkProtocol(5)

    self.assertEqual(7, protocol + 2)
    self.assertEqual(3, protocol - 2)
    self.assertEqual(15, protocol * 3)
    self.assertEqual(1, protocol // 3)
Exemple #6
0
    def _pack(cls, link_protocol, payload, circ_id=None):
        """
    Provides bytes that can be used on the wire for these cell attributes.
    Format of a properly packed cell depends on if it's fixed or variable
    sized...

    ::

      Fixed:    [ CircuitID ][ Command ][ Payload ][ Padding ]
      Variable: [ CircuitID ][ Command ][ Size ][ Payload ]

    :param str name: cell command
    :param int link_protocol: link protocol version
    :param bytes payload: cell payload
    :param int circ_id: circuit id, if a CircuitCell

    :return: **bytes** with the encoded payload

    :raise: **ValueError** if cell type invalid or payload makes cell too large
    """

        if issubclass(cls, CircuitCell):
            if circ_id is None:
                raise ValueError('%s cells require a circuit identifier' %
                                 cls.NAME)
            elif circ_id < 1:
                raise ValueError(
                    'Circuit identifiers must a positive integer, not %s' %
                    circ_id)
        else:
            if circ_id is not None:
                raise ValueError(
                    '%s cells should not specify a circuit identifier' %
                    cls.NAME)

            circ_id = 0  # cell doesn't concern a circuit, default field to zero

        link_protocol = LinkProtocol.for_version(link_protocol)

        cell = bytearray()
        cell += link_protocol.circ_id_size.pack(circ_id)
        cell += Size.CHAR.pack(cls.VALUE)
        cell += b'' if cls.IS_FIXED_SIZE else Size.SHORT.pack(len(payload))
        cell += payload

        # pad fixed sized cells to the required length

        if cls.IS_FIXED_SIZE:
            if len(cell) > link_protocol.fixed_cell_len:
                raise ValueError(
                    'Cell of type %s is too large (%i bytes), must not be more than %i. Check payload size (was %i bytes)'
                    % (cls.NAME, len(cell), link_protocol.fixed_cell_len,
                       len(payload)))

            cell += ZERO * (link_protocol.fixed_cell_len - len(cell))

        return bytes(cell)
Exemple #7
0
  def __init__(self, orport, link_protocol):
    # TODO: Python 3.x adds a getbuffer() method which
    # lets us get the size...
    #
    #   https://stackoverflow.com/questions/26827055/python-how-to-get-iobytes-allocated-memory-length
    #
    # When we drop python 2.x support we should replace
    # self._orport_buffer with an io.BytesIO.

    self.link_protocol = LinkProtocol(link_protocol)
    self._orport = orport
    self._orport_buffer = b''  # unread bytes
    self._orport_lock = threading.RLock()
    self._circuits = {}
Exemple #8
0
 def __init__(self, orport, link_protocol):
   self.link_protocol = LinkProtocol(link_protocol)
   self._orport = orport
   self._orport_lock = threading.RLock()
   self._circuits = {}