Exemplo n.º 1
0
    def test_stream_close_behavior(self):
        # Prepare a socket so we can open a stream.
        sock = DummySocket()
        c = HTTP20Connection('www.google.com')
        c._sock = sock

        # Open a few requests (which creates a stream)
        s1 = c.request('GET', '/')
        c.request('GET', '/')

        # simulate state of blocking on read while sock
        f = GoAwayFrame(0)
        # Set error code to PROTOCOL_ERROR
        f.error_code = 1
        c._sock.buffer = BytesIO(f.serialize())

        # 'Receive' the GOAWAY frame.
        # Validate that the spec error name and description are used to throw
        # the connection exception.
        with pytest.raises(ConnectionError):
            c.get_response(s1)

        # try to read again after close
        with pytest.raises(ConnectionError):
            c._single_read()
Exemplo n.º 2
0
    def test_stream_close_behavior(self):
        # Prepare a socket so we can open a stream.
        sock = DummySocket()
        c = HTTP20Connection('www.google.com')
        c._sock = sock

        # Open a few requests (which creates a stream)
        s1 = c.request('GET', '/')
        c.request('GET', '/')

        # simulate state of blocking on read while sock
        f = GoAwayFrame(0)
        # Set error code to PROTOCOL_ERROR
        f.error_code = 1
        c._sock.buffer = BytesIO(f.serialize())

        # 'Receive' the GOAWAY frame.
        # Validate that the spec error name and description are used to throw
        # the connection exception.
        with pytest.raises(ConnectionError):
            c.get_response(s1)

        # try to read again after close
        with pytest.raises(ConnectionError):
            c._single_read()
Exemplo n.º 3
0
 def build_goaway_frame(self, last_stream_id, error_code=0):
     """
     Builds a single GOAWAY frame.
     """
     f = GoAwayFrame(0)
     f.error_code = error_code
     f.last_stream_id = last_stream_id
     return f
Exemplo n.º 4
0
 def build_goaway_frame(self, last_stream_id, error_code=0):
     """
     Builds a single GOAWAY frame.
     """
     f = GoAwayFrame(0)
     f.error_code = error_code
     f.last_stream_id = last_stream_id
     return f
Exemplo n.º 5
0
 def test_repr(self):
     f = GoAwayFrame()
     assert repr(f).endswith(
         "last_stream_id=0, error_code=0, additional_data=b''")
     f.last_stream_id = 64
     f.error_code = 32
     f.additional_data = b'hello'
     assert repr(f).endswith(
         "last_stream_id=64, error_code=32, additional_data=b'hello'")
Exemplo n.º 6
0
 def _terminate_connection(self, error_code):
     """
     Terminate the connection early. Used in error handling blocks to send
     GOAWAY frames.
     """
     f = GoAwayFrame(0)
     f.last_stream_id = self.highest_inbound_stream_id
     f.error_code = error_code
     self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY)
     self._prepare_for_sending([f])
Exemplo n.º 7
0
 def _terminate_connection(self, error_code):
     """
     Terminate the connection early. Used in error handling blocks to send
     GOAWAY frames.
     """
     f = GoAwayFrame(0)
     f.last_stream_id = self.highest_inbound_stream_id
     f.error_code = error_code
     self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY)
     self._prepare_for_sending([f])
Exemplo n.º 8
0
 def build_goaway_frame(self,
                        last_stream_id,
                        error_code=0,
                        additional_data=b''):
     """
     Builds a single GOAWAY frame.
     """
     f = GoAwayFrame(0)
     f.error_code = error_code
     f.last_stream_id = last_stream_id
     f.additional_data = additional_data
     return f
Exemplo n.º 9
0
 def build_goaway_frame(self,
                        last_stream_id,
                        error_code=0,
                        additional_data=b''):
     """
     Builds a single GOAWAY frame.
     """
     f = GoAwayFrame(0)
     f.error_code = error_code
     f.last_stream_id = last_stream_id
     f.additional_data = additional_data
     return f
Exemplo n.º 10
0
    def close_connection(self, error_code=0):
        """
        Close a connection, emitting a GOAWAY frame.
        """
        self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY)

        f = GoAwayFrame(0)
        f.error_code = error_code
        f.last_stream_id = self.highest_stream_id
        self._prepare_for_sending([f])

        return []
Exemplo n.º 11
0
    def close_connection(self, error_code=0):
        """
        Close a connection, emitting a GOAWAY frame.
        """
        self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY)

        f = GoAwayFrame(0)
        f.error_code = error_code
        f.last_stream_id = self.highest_stream_id
        self._prepare_for_sending([f])

        return []
Exemplo n.º 12
0
    def test_goaway_frame_NO_ERROR(self):
        f = GoAwayFrame(0)
        # Set error code to NO_ERROR
        f.error_code = 0

        c = HTTP20Connection('www.google.com')
        c._sock = DummySocket()
        c._sock.buffer = BytesIO(f.serialize())

        # 'Receive' the GOAWAY frame.
        # Test makes sure no exception is raised; error code 0 means we are
        # dealing with a standard and graceful shutdown.
        c._single_read()
Exemplo n.º 13
0
    def test_goaway_serializes_properly(self):
        f = GoAwayFrame(0)
        f.last_stream_id = 64
        f.error_code = 32
        f.additional_data = b'hello'

        s = f.serialize()
        assert s == (
            b'\x00\x00\x0D\x07\x00\x00\x00\x00\x00' +  # Frame header
            b'\x00\x00\x00\x40'                     +  # Last Stream ID
            b'\x00\x00\x00\x20'                     +  # Error Code
            b'hello'                                   # Additional data
        )
Exemplo n.º 14
0
    def test_goaway_frame_NO_ERROR(self):
        f = GoAwayFrame(0)
        # Set error code to NO_ERROR
        f.error_code = 0

        c = HTTP20Connection('www.google.com')
        c._sock = DummySocket()
        c._sock.buffer = BytesIO(f.serialize())

        # 'Receive' the GOAWAY frame.
        # Test makes sure no exception is raised; error code 0 means we are
        # dealing with a standard and graceful shutdown.
        c._single_read()
Exemplo n.º 15
0
    def close_connection(self, error_code=0):
        """
        Close a connection, emitting a GOAWAY frame.

        :param error_code: (optional) The error code to send in the GOAWAY
            frame.
        :returns: Nothing
        """
        self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY)

        f = GoAwayFrame(0)
        f.error_code = error_code
        f.last_stream_id = self.highest_inbound_stream_id
        self._prepare_for_sending([f])
Exemplo n.º 16
0
    def close_connection(self, error_code=0):
        """
        Close a connection, emitting a GOAWAY frame.

        :param error_code: (optional) The error code to send in the GOAWAY
            frame.
        :returns: Nothing
        """
        self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY)

        f = GoAwayFrame(0)
        f.error_code = error_code
        f.last_stream_id = self.highest_inbound_stream_id
        self._prepare_for_sending([f])
Exemplo n.º 17
0
        def socket_handler(listener):
            sock = listener.accept()[0]

            # We should get one packet. Rather than respond to it, send a
            # GOAWAY frame with error code 0 indicating clean shutdown.
            sock.recv(65535)

            # Now, send the shut down.
            f = GoAwayFrame(0)
            f.error_code = 1
            sock.send(f.serialize())

            # Wait for the message from the main thread.
            sock.close()
            recv_event.set()
Exemplo n.º 18
0
        def socket_handler(listener):
            sock = listener.accept()[0]

            # We should get one packet. Rather than respond to it, send a
            # GOAWAY frame with error code 0 indicating clean shutdown.
            sock.recv(65535)

            # Now, send the shut down.
            f = GoAwayFrame(0)
            f.error_code = 1
            sock.send(f.serialize())

            # Wait for the message from the main thread.
            sock.close()
            recv_event.set()
Exemplo n.º 19
0
    def test_goaway_frame_invalid_error_code(self):
        f = GoAwayFrame(0)
        # Set error code to non existing error
        f.error_code = 100

        c = HTTP20Connection('www.google.com')
        c._sock = DummySocket()
        c._sock.buffer = BytesIO(f.serialize())

        # 'Receive' the GOAWAY frame.
        # If the error code does not exist in the spec then the additional
        # data is used instead.
        with pytest.raises(ConnectionError) as conn_err:
            c._single_read()

        err_msg = str(conn_err)
        with pytest.raises(ValueError):
            name, number, description = errors.get_data(100)

        assert str(f.error_code) in err_msg
Exemplo n.º 20
0
    def test_goaway_frame_invalid_error_code(self):
        f = GoAwayFrame(0)
        # Set error code to non existing error
        f.error_code = 100

        c = HTTP20Connection('www.google.com')
        c._sock = DummySocket()
        c._sock.buffer = BytesIO(f.serialize())

        # 'Receive' the GOAWAY frame.
        # If the error code does not exist in the spec then the additional
        # data is used instead.
        with pytest.raises(ConnectionError) as conn_err:
            c._single_read()

        err_msg = str(conn_err)
        with pytest.raises(ValueError):
            name, number, description = errors.get_data(100)

        assert str(f.error_code) in err_msg
Exemplo n.º 21
0
    def test_goaway_frame_PROTOCOL_ERROR(self):
        f = GoAwayFrame(0)
        # Set error code to PROTOCOL_ERROR
        f.error_code = 1

        c = HTTP20Connection('www.google.com')
        c._sock = DummySocket()
        c._sock.buffer = BytesIO(f.serialize())

        # 'Receive' the GOAWAY frame.
        # Validate that the spec error name and description are used to throw
        # the connection exception.
        with pytest.raises(ConnectionError) as conn_err:
            c._single_read()

        err_msg = str(conn_err)
        name, number, description = errors.get_data(1)

        assert name in err_msg
        assert number in err_msg
        assert description in err_msg
Exemplo n.º 22
0
    def test_goaway_frame_HTTP_1_1_REQUIRED(self):
        f = GoAwayFrame(0)
        # Set error code to HTTP_1_1_REQUIRED
        f.error_code = 13

        c = HTTP20Connection('www.google.com')
        c._sock = DummySocket()
        c._sock.buffer = BytesIO(f.serialize())

        # 'Receive' the GOAWAY frame.
        # Validate that the spec error name and description are used to throw
        # the connection exception.
        with pytest.raises(ConnectionError) as conn_err:
            c._single_read()

        err_msg = str(conn_err)
        name, number, description = errors.get_data(13)

        assert name in err_msg
        assert number in err_msg
        assert description in err_msg
Exemplo n.º 23
0
    def receive_frame(self, frame):
        """
        Handle a frame received on the connection.
        """
        try:
            if frame.body_len > self.max_inbound_frame_size:
                raise ProtocolError(
                    "Received overlong frame: length %d, max %d" %
                    (frame.body_len, self.max_inbound_frame_size)
                )

            # I don't love using __class__ here, maybe reconsider it.
            frames, events = self._frame_dispatch_table[frame.__class__](frame)
        except ProtocolError as e:
            # For whatever reason, receiving the frame caused a protocol error.
            # We should prepare to emit a GoAway frame before throwing the
            # exception up further. No need for an event: the exception will
            # do fine.
            f = GoAwayFrame(0)
            f.last_stream_id = sorted(self.streams.keys())[-1]
            f.error_code = e.error_code
            self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY)
            self._prepare_for_sending([f])
            raise
        except StreamClosedError as e:
            # We need to send a RST_STREAM frame on behalf of the stream.
            # The frame the stream wants to emit is already present in the
            # exception.
            # This does not require re-raising: it's an expected behaviour.
            f = RstStreamFrame(e.stream_id)
            f.error_code = e.error_code
            self._prepare_for_sending([f])
            events = []
        else:
            self._prepare_for_sending(frames)

        return events
Exemplo n.º 24
0
    def test_goaway_serializes_properly(self):
        f = GoAwayFrame()
        f.last_stream_id = 64
        f.error_code = 32
        f.additional_data = b'hello'

        s = f.serialize()
        assert s == (
            b'\x00\x00\x0D\x07\x00\x00\x00\x00\x00' +  # Frame header
            b'\x00\x00\x00\x40' +  # Last Stream ID
            b'\x00\x00\x00\x20' +  # Error Code
            b'hello'  # Additional data
        )
Exemplo n.º 25
0
    def test_resetting_streams_after_close(self):
        """
        Attempts to reset streams when the connection is torn down are
        tolerated.
        """
        f = SettingsFrame(0)

        c = HTTP20Connection('www.google.com')
        c._sock = DummySocket()
        c._sock.buffer = BytesIO(f.serialize())

        # Open stream 1.
        c.request('GET', '/')

        # Swap out the buffer to get a GoAway frame.
        f = GoAwayFrame(0)
        f.error_code = 1
        c._sock.buffer = BytesIO(f.serialize())

        # "Read" the GoAway
        with pytest.raises(ConnectionError):
            c._single_read()
Exemplo n.º 26
0
    def receive_frame(self, frame):
        """
        Handle a frame received on the connection.
        """
        try:
            if frame.body_len > self.max_inbound_frame_size:
                raise ProtocolError(
                    "Received overlong frame: length %d, max %d" %
                    (frame.body_len, self.max_inbound_frame_size))

            # I don't love using __class__ here, maybe reconsider it.
            frames, events = self._frame_dispatch_table[frame.__class__](frame)
        except ProtocolError as e:
            # For whatever reason, receiving the frame caused a protocol error.
            # We should prepare to emit a GoAway frame before throwing the
            # exception up further. No need for an event: the exception will
            # do fine.
            f = GoAwayFrame(0)
            f.last_stream_id = sorted(self.streams.keys())[-1]
            f.error_code = e.error_code
            self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY)
            self._prepare_for_sending([f])
            raise
        except StreamClosedError as e:
            # We need to send a RST_STREAM frame on behalf of the stream.
            # The frame the stream wants to emit is already present in the
            # exception.
            # This does not require re-raising: it's an expected behaviour.
            f = RstStreamFrame(e.stream_id)
            f.error_code = e.error_code
            self._prepare_for_sending([f])
            events = []
        else:
            self._prepare_for_sending(frames)

        return events
Exemplo n.º 27
0
    def test_go_away_has_no_flags(self):
        f = GoAwayFrame(0)
        flags = f.parse_flags(0xFF)

        assert not flags
        assert isinstance(flags, set)
Exemplo n.º 28
0
 def test_goaway_frame_never_has_a_stream(self):
     with pytest.raises(ValueError):
         GoAwayFrame(stream_id=1)
Exemplo n.º 29
0
    def test_go_away_has_no_flags(self):
        f = GoAwayFrame()
        flags = f.parse_flags(0xFF)

        assert not flags
        assert isinstance(flags, Flags)
Exemplo n.º 30
0
 def test_goaway_frame_never_has_a_stream(self):
     with pytest.raises(InvalidDataError):
         GoAwayFrame(1)