示例#1
0
    def test_that_receiving_wrongly_encoded_message_should_return_none(
            self, unused_tcp_port):
        middleman_message = GolemMessageFrame(Ping(), self.request_id)
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY, )

        raw_message_encoded = escape_encode_raw_message(raw_message)
        raw_message_encoded = raw_message_encoded + ESCAPE_CHARACTER + b'\xff'
        raw_message_encoded = append_frame_separator(raw_message_encoded)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                client_socket.send(raw_message_encoded)
                raw_message_received = next(
                    unescape_stream(connection=connection))

        assertpy.assert_that(raw_message_received).is_none()
示例#2
0
    def test_that_receiving_a_series_of_messages_should_be_handled_correctly(
            self, unused_tcp_port):
        payload = Ping()
        middleman_message = GolemMessageFrame(payload, self.request_id)
        raw_message = escape_encode_raw_message(
            middleman_message.serialize(private_key=CONCENT_PRIVATE_KEY))
        raw_message_with_separator = append_frame_separator(raw_message)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                for _i in range(10):
                    client_socket.send(raw_message_with_separator)

                split_stream_generator = split_stream(connection=connection)

                for _i in range(10):
                    raw_message_received = next(split_stream_generator)

                    assertpy.assert_that(raw_message).is_equal_to(
                        raw_message_received)
 def test_that_sci_callback_should_raise_exception_when_response_is_not_signed_transaction_golem_message(self):
     with mock.patch('core.payments.sci_callback.socket.socket.connect'):
         with mock.patch('core.payments.sci_callback.send_over_stream'):
             with mock.patch('core.payments.sci_callback.unescape_stream', side_effect=self.frame_iterator):
                 with mock.patch(
                     'middleman_protocol.message.AbstractFrame.deserialize',
                     return_value=GolemMessageFrame(payload=Ping(), request_id=self.request_id),
                 ):
                     with self.assertRaises(SCICallbackPayloadError):
                         sci_callback(self.transaction)
示例#4
0
def test_that_sent_data_is_escaped_and_contains_frame_separator(event_loop):
    frame = GolemMessageFrame(Ping(), 777)
    expected_data = append_frame_separator(
        escape_encode_raw_message(frame.serialize(CONCENT_PRIVATE_KEY)))
    mocked_writer = prepare_mocked_writer()

    task = _run_test_in_event_loop(event_loop, send_over_stream_async, frame,
                                   mocked_writer, CONCENT_PRIVATE_KEY)

    assert_that(task.done()).is_true()
    mocked_writer.write.assert_called_once_with(expected_data)
    mocked_writer.drain.mock.assert_called_once_with()
示例#5
0
    def test_that_serializing_different_golem_message_middleman_messages_should_keep_part_of_header_the_same(
            self):
        message_1 = GolemMessageFrame(
            ServiceRefused(reason=ServiceRefused.REASON.InvalidRequest),
            self.request_id).serialize(private_key=CONCENT_PRIVATE_KEY)
        message_2 = GolemMessageFrame(
            Ping(), self.request_id).serialize(private_key=CONCENT_PRIVATE_KEY)

        assertpy.assert_that(
            message_1[FRAME_SIGNATURE_BYTES_LENGTH:FRAME_PAYLOAD_STARTING_BYTE]
        ).is_equal_to(
            message_2[FRAME_SIGNATURE_BYTES_LENGTH:FRAME_PAYLOAD_STARTING_BYTE]
        )
示例#6
0
def test_that_when_frame_with_escaped_sequence_and_separator_is_received_unescaped_frame_is_returned(
        event_loop):
    golem_message_frame = GolemMessageFrame(Ping(), 777)
    data_to_send = escape_encode_raw_message(
        golem_message_frame.serialize(CONCENT_PRIVATE_KEY)
    ) + ESCAPE_SEQUENCES[ESCAPE_CHARACTER] + FRAME_SEPARATOR
    mocked_reader = prepare_mocked_reader(data_to_send)

    task = _run_test_in_event_loop(event_loop, handle_frame_receive_async,
                                   mocked_reader, CONCENT_PUBLIC_KEY)

    assert_that(task.done()).is_true()
    mocked_reader.readuntil.mock.assert_called_once_with(FRAME_SEPARATOR)
    assert_that(task.result()).is_equal_to(golem_message_frame)
def is_concent_api_running(api_url: str) -> bool:
    """ Verifies if Concent API server instance is running on given API url. """
    try:
        response = requests.post(
            api_url,
            data=Ping().serialize(),
            headers={
                'Content-Type': 'application/octet-stream',
            },
            verify=False,
        )
        return (response.json()['error'] == 'Unknown message type'
                and response.json()['error_code'] == 'message.unknown')
    except requests.ConnectionError:
        return False
示例#8
0
    def test_that_exceeding_maximum_frame_length_should_treat_exceeded_frame_as_invalid(
            self, unused_tcp_port):
        first_middleman_message = GolemMessageFrame(Ping(), self.request_id)
        first_raw_message = append_frame_separator(
            escape_encode_raw_message(
                first_middleman_message.serialize(
                    private_key=CONCENT_PRIVATE_KEY)))
        second_middleman_message = AuthenticationChallengeFrame(
            payload=b'',
            request_id=100,
        )
        second_raw_message = append_frame_separator(
            escape_encode_raw_message(
                second_middleman_message.serialize(
                    private_key=CONCENT_PRIVATE_KEY)))

        assert len(first_raw_message) > len(second_raw_message) + 10

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                client_socket.send(first_raw_message)
                client_socket.send(second_raw_message)

                with mock.patch(
                        'middleman_protocol.stream.MAXIMUM_FRAME_LENGTH',
                        len(first_raw_message) - 10):
                    raw_message_received = next(
                        unescape_stream(connection=connection))

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=CONCENT_PUBLIC_KEY,
        )

        assertpy.assert_that(deserialized_message.request_id).is_equal_to(100)
示例#9
0
 def setUp(self, unused_tcp_port_factory, event_loop):
     golem_message_frame = GolemMessageFrame(
         Ping(), 777).serialize(CONCENT_PRIVATE_KEY)
     self.patcher = mock.patch("middleman.middleman_server.crash_logger")
     self.crash_logger_mock = self.patcher.start()
     self.internal_port, self.external_port = unused_tcp_port_factory(
     ), unused_tcp_port_factory()
     self.data_to_send = append_frame_separator(
         escape_encode_raw_message(golem_message_frame))
     self.timeout = 0.2
     self.short_delay = 0.1
     self.middleman = MiddleMan(internal_port=self.internal_port,
                                external_port=self.external_port,
                                loop=event_loop)
     yield self.internal_port, self.external_port
     self.patcher.stop()
示例#10
0
 def setUp(self, event_loop):
     self.mocked_writer = prepare_mocked_writer()
     self.message_tracker = OrderedDict({})
     self.golem_message = Ping()
     sign_message(self.golem_message, CONCENT_PRIVATE_KEY)
     self.connection_id = 4
     self.request_id = 888
     self.queue = Queue(loop=event_loop)
     self.queue_pool = QueuePool(
         {self.connection_id: Queue(loop=event_loop)},
         loop=event_loop,
     )
     self.signing_service_request_id = 1
     self.request_queue_item = RequestQueueItem(
         self.connection_id,
         self.request_id,
         self.golem_message,
         FROZEN_TIMESTAMP
     )
示例#11
0
    def test_that_receiving_a_series_of_messages_should_be_handled_correctly(
            self, unused_tcp_port):
        payload = Ping()
        middleman_message = GolemMessageFrame(payload, self.request_id)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                for _i in range(10):
                    send_over_stream(connection=client_socket,
                                     raw_message=middleman_message,
                                     private_key=CONCENT_PRIVATE_KEY)

                unescape_stream_generator = unescape_stream(
                    connection=connection)

                for _i in range(10):
                    raw_message_received = next(unescape_stream_generator)

                    deserialized_message = AbstractFrame.deserialize(
                        raw_message=raw_message_received,
                        public_key=CONCENT_PUBLIC_KEY,
                    )

                    assertpy.assert_that(deserialized_message).is_instance_of(
                        GolemMessageFrame)
                    assertpy.assert_that(
                        deserialized_message.payload).is_instance_of(Ping)
                    assertpy.assert_that(
                        deserialized_message.payload).is_equal_to(payload)
    def setUp(self):
        super().setUp()

        self.v = 28
        self.r = 43021479287739768723523510158222935518435169120980980279247970098168969365906
        self.s = 27167722793113753385347871828548141783025585937756999455305671053201800240244

        self.request_id = RequestIDGenerator.generate_request_id() + 1
        self.transaction = self._create_unsigned_transaction()
        self.signed_transaction_golem_message = self._create_signed_transaction()
        self.signed_transaction_golem_message.sign_message(SIGNING_SERVICE_PRIVATE_KEY)
        self.frame = GolemMessageFrame(
            payload=self.signed_transaction_golem_message,
            request_id=self.request_id,
        ).serialize(private_key=CONCENT_PRIVATE_KEY)

        def iterator(connection):  # pylint: disable=unused-argument
            yield self.frame

        self.frame_iterator = iterator
        self.middleman_message = GolemMessageFrame(payload=Ping(), request_id=self.request_id)
def test_case_ping_message_send_to_concent_with_malformed_golem_messages_should_get_http400_response_with_bad_request_error(
    cluster_url: str,
    cluster_consts: ProtocolConstants,
    concent_1_golem_messages_version: str,
    concent_2_golem_messages_version: str,
) -> None:
    # Sending Ping message to concent with malformed header(Golem Messages version has a wrong, non-semver format).
    # Expected: ngingx-router will respond with Http400 with error code "bad-request".
    api_request(
        cluster_url,
        'send',
        PROVIDER_PRIVATE_KEY,
        CONCENT_PUBLIC_KEY,
        Ping(),
        headers={
            'Content-Type': 'application/octet-stream',
            'X-Golem-Messages': 'X.X.X'
        },
        expected_status=400,
        expected_error_code='bad-request',
    )
def test_case_ping_message_send_to_concent_with_unsupported_golem_messages_should_get_http404_response_with_not_found_error(
    cluster_url: str,
    cluster_consts: ProtocolConstants,
    concent_1_golem_messages_version: str,
    concent_2_golem_messages_version: str,
) -> None:
    # Sending Ping message to concent with unsupported version of Golem Messages.
    # Expected: nginx-router will respond with Http404.
    api_request(
        cluster_url,
        'send',
        PROVIDER_PRIVATE_KEY,
        CONCENT_PUBLIC_KEY,
        Ping(),
        headers={
            'Content-Type': 'application/octet-stream',
            'X-Golem-Messages': '1.0.0'
        },
        expected_status=404,
        expected_error_code='not-found',
    )
示例#15
0
    def setUp(self, event_loop):
        self.first_index = 1
        self.second_index = 2
        ping_message = Ping()
        resposne_queue_items = [
            ResponseQueueItem(ping_message, 777, get_current_utc_timestamp()),
            ResponseQueueItem(ping_message, 888, get_current_utc_timestamp()),
            ResponseQueueItem(ping_message, 1001, get_current_utc_timestamp()),
            ResponseQueueItem(ping_message, 1007, get_current_utc_timestamp()),
        ]
        first_queue = asyncio.Queue(loop=event_loop)
        second_queue = asyncio.Queue(loop=event_loop)

        self.number_of_items_in_first_queue = 3
        event_loop.run_until_complete(self._populate_queues(first_queue, resposne_queue_items, second_queue))

        self.initial_dict = {
            self.first_index: first_queue,
            self.second_index: second_queue,
        }
        self.logger_mock = create_autospec(spec=Logger, spec_set=True)
        self.queue_pool = QueuePool(self.initial_dict, event_loop, self.logger_mock)
示例#16
0
    def test_that_receiving_encoded_message_should_decode_on_the_fly(
            self, unused_tcp_port):
        middleman_message = GolemMessageFrame(Ping(), self.request_id)
        raw_message = append_frame_separator(
            middleman_message.serialize(private_key=CONCENT_PRIVATE_KEY))

        raw_message = raw_message[:10] + ESCAPE_CHARACTER + raw_message[
            len(ESCAPE_CHARACTER) + 10:]
        raw_message_encoded = escape_encode_raw_message(raw_message)

        assert FRAME_SEPARATOR not in raw_message_encoded

        raw_message_encoded = append_frame_separator(raw_message_encoded)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                client_socket.send(raw_message_encoded)
                raw_message_received = next(
                    unescape_stream(connection=connection))

        assertpy_bytes_starts_with(raw_message, raw_message_received)
        assertpy.assert_that(
            len(raw_message_received)).is_greater_than_or_equal_to(
                FRAME_PAYLOAD_STARTING_BYTE)
    def test_that__handle_connection_should_send_error_frame_if_payload_is_invalid(
            self):
        # Prepare frame payload which is not Golem message.
        middleman_message = GolemMessageFrame(
            payload=Ping(),
            request_id=99,
        )
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)
        malformed_raw_message = (
            raw_message[:FRAME_PAYLOAD_STARTING_BYTE] +
            AbstractFrame.get_frame_format(
            ).signed_part_of_the_frame.payload.build(b'\x00' * 100))

        # Replace message signature
        new_signature = ecdsa_sign(
            CONCENT_PRIVATE_KEY,
            malformed_raw_message[FRAME_SIGNATURE_BYTES_LENGTH:])
        malformed_raw_message_with_new_signature = new_signature + malformed_raw_message[
            FRAME_SIGNATURE_BYTES_LENGTH:]

        raw_message_received = self._prepare_and_execute_handle_connection(
            malformed_raw_message_with_new_signature)

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=SIGNING_SERVICE_PUBLIC_KEY,
        )

        assertpy.assert_that(
            deserialized_message.payload).is_instance_of(tuple)
        assertpy.assert_that(deserialized_message.payload).is_length(2)
        assertpy.assert_that(deserialized_message.payload[0]).is_equal_to(
            ErrorCode.InvalidPayload)
        assertpy.assert_that(deserialized_message.request_id).is_equal_to(
            REQUEST_ID_FOR_RESPONSE_FOR_INVALID_FRAME)
示例#18
0
class TestMessageMiddlemanProtocol:

    request_id = 99

    @pytest.mark.parametrize(
        ('expected_middleman_message_type', 'payload_type', 'payload'), [
            (GolemMessageFrame, PayloadType.GOLEM_MESSAGE, Ping()),
            (ErrorFrame, PayloadType.ERROR, (111, 'error_message')),
            (AuthenticationChallengeFrame,
             PayloadType.AUTHENTICATION_CHALLENGE, b'random_bytes'),
            (AuthenticationResponseFrame, PayloadType.AUTHENTICATION_RESPONSE,
             b'TODO'),
            (HeartbeatFrame, PayloadType.HEARTBEAT, None),
        ])
    def test_that_create_middleman_protocol_message_with_various_payload_types_should_create_proper_middleman_message(
        self,
        expected_middleman_message_type,
        payload_type,
        payload,
    ):
        message = create_middleman_protocol_message(
            payload_type,
            payload,
            self.request_id,
        )

        assertpy.assert_that(message).is_instance_of(
            expected_middleman_message_type)
        assertpy.assert_that(message.payload_type).is_equal_to(payload_type)

    def test_that_abstract_middleman_message_instantiation_should_raise_exception(
            self):
        with pytest.raises(TypeError):
            AbstractFrame(  # pylint: disable=abstract-class-instantiated
                Ping(),
                self.request_id,
            )

    @pytest.mark.parametrize(('middleman_message_type', 'payload'), [
        (GolemMessageFrame, Ping()),
        (ErrorFrame, (111, 'error_message')),
        (AuthenticationChallengeFrame, b'random_bytes'),
        (AuthenticationResponseFrame, b'TODO'),
        (HeartbeatFrame, None),
    ])
    def test_that_serializing_and_deserializing_message_should_preserve_original_data(
        self,
        middleman_message_type,
        payload,
    ):
        middleman_message = middleman_message_type(payload, self.request_id)
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)
        deserialized_message = AbstractFrame.deserialize(
            raw_message,
            public_key=CONCENT_PUBLIC_KEY,
        )

        assertpy.assert_that(deserialized_message).is_instance_of(
            middleman_message_type)
        assertpy.assert_that(deserialized_message.payload).is_instance_of(
            type(payload))
        assertpy.assert_that(deserialized_message.payload).is_equal_to(payload)

    @pytest.mark.parametrize(('middleman_message_type', 'payload'), [
        (GolemMessageFrame, Ping()),
        (ErrorFrame, (111, 'error_message')),
        (AuthenticationChallengeFrame, b'random_bytes'),
        (AuthenticationResponseFrame, b'TODO'),
        (HeartbeatFrame, None),
    ])
    def test_that_sending_message_over_tcp_socket_should_preserve_original_data(
        self,
        middleman_message_type,
        payload,
        unused_tcp_port,
    ):
        middleman_message = middleman_message_type(payload, self.request_id)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                send_over_stream(connection=client_socket,
                                 raw_message=middleman_message,
                                 private_key=CONCENT_PRIVATE_KEY)
                raw_message_received = next(
                    unescape_stream(connection=connection))

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=CONCENT_PUBLIC_KEY,
        )

        assertpy.assert_that(deserialized_message).is_instance_of(
            middleman_message_type)
        assertpy.assert_that(deserialized_message.payload).is_instance_of(
            type(payload))
        assertpy.assert_that(deserialized_message.payload).is_equal_to(payload)

    def test_that_serializing_different_golem_message_middleman_messages_should_keep_part_of_header_the_same(
            self):
        message_1 = GolemMessageFrame(
            ServiceRefused(reason=ServiceRefused.REASON.InvalidRequest),
            self.request_id).serialize(private_key=CONCENT_PRIVATE_KEY)
        message_2 = GolemMessageFrame(
            Ping(), self.request_id).serialize(private_key=CONCENT_PRIVATE_KEY)

        assertpy.assert_that(
            message_1[FRAME_SIGNATURE_BYTES_LENGTH:FRAME_PAYLOAD_STARTING_BYTE]
        ).is_equal_to(
            message_2[FRAME_SIGNATURE_BYTES_LENGTH:FRAME_PAYLOAD_STARTING_BYTE]
        )

    @pytest.mark.parametrize(('middleman_message_type', 'payload'), [
        (GolemMessageFrame, Ping()),
        (ErrorFrame, (111, 'error_message')),
        (AuthenticationChallengeFrame, b'random_bytes'),
        (AuthenticationResponseFrame, b'TODO'),
        (HeartbeatFrame, None),
    ])
    def test_that_serializing_and_deserializing_message_with_wrong_signature_should_raise_exception(
        self,
        middleman_message_type,
        payload,
    ):
        middleman_message = middleman_message_type(payload, self.request_id)
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)

        first_byte = 2 if raw_message[0] == 0 else raw_message[0]
        malformed_raw_message = bytes(bytearray([first_byte - 1
                                                 ])) + raw_message[1:]

        with pytest.raises(SignatureInvalidMiddlemanProtocolError):
            AbstractFrame.deserialize(
                malformed_raw_message,
                CONCENT_PUBLIC_KEY,
            )

    def test_that_serializing_and_deserializing_message_with_wrong_payload_type_should_raise_exception(
            self):
        middleman_message = GolemMessageFrame(Ping(), self.request_id)
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)

        payload_type_position = FRAME_SIGNATURE_BYTES_LENGTH + FRAME_REQUEST_ID_BYTES_LENGTH
        invalid_payload_type = 100

        # Sanity check for payload type in this case to be between expected bytes
        assert raw_message[payload_type_position:payload_type_position +
                           1] == b'\x00'
        assert invalid_payload_type not in PAYLOAD_TYPE_TO_MIDDLEMAN_MESSAGE_CLASS

        # Replace bytes with payload length
        raw_message = (
            raw_message[:payload_type_position] +
            bytes(bytearray([invalid_payload_type])) +
            raw_message[payload_type_position + FRAME_PAYLOAD_TYPE_LENGTH:])

        # Replace message signature
        new_signature = ecdsa_sign(CONCENT_PRIVATE_KEY,
                                   raw_message[FRAME_SIGNATURE_BYTES_LENGTH:])
        raw_message_with_new_signature = new_signature + raw_message[
            FRAME_SIGNATURE_BYTES_LENGTH:]

        with pytest.raises(PayloadTypeInvalidMiddlemanProtocolError):
            AbstractFrame.deserialize(raw_message_with_new_signature,
                                      CONCENT_PUBLIC_KEY)

    @pytest.mark.parametrize(('middleman_message_type', 'payload'), [
        (GolemMessageFrame, Ping()),
        (ErrorFrame, (111, 'error_message')),
        (AuthenticationChallengeFrame, b'random_bytes'),
        (AuthenticationResponseFrame, b'TODO'),
        (HeartbeatFrame, None),
    ])
    def test_that_serializing_and_deserializing_message_too_short_should_raise_exception(
        self,
        middleman_message_type,
        payload,
    ):
        middleman_message = middleman_message_type(payload, self.request_id)
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)

        malformed_raw_message = raw_message[:-1]

        with pytest.raises(FrameInvalidMiddlemanProtocolError):
            AbstractFrame.deserialize(
                malformed_raw_message,
                CONCENT_PUBLIC_KEY,
            )
示例#19
0
class TestUnescapeStreamHelperMiddlemanProtocol:

    request_id = 99

    @pytest.mark.parametrize(('middleman_message_type', 'payload'), [
        (GolemMessageFrame, Ping()),
        (ErrorFrame, (111, 'error_message')),
        (AuthenticationChallengeFrame, b'random_bytes'),
        (AuthenticationResponseFrame, b'TODO'),
    ])
    def test_that_receiving_any_message_should_be_handled_correctly(
        self,
        middleman_message_type,
        payload,
        unused_tcp_port,
    ):
        middleman_message = middleman_message_type(payload, self.request_id)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                send_over_stream(connection=client_socket,
                                 raw_message=middleman_message,
                                 private_key=CONCENT_PRIVATE_KEY)
                raw_message_received = next(
                    unescape_stream(connection=connection))

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=CONCENT_PUBLIC_KEY,
        )

        assertpy.assert_that(deserialized_message).is_instance_of(
            middleman_message_type)
        assertpy.assert_that(deserialized_message.payload).is_equal_to(payload)

    def test_that_receiving_a_series_of_messages_should_be_handled_correctly(
            self, unused_tcp_port):
        payload = Ping()
        middleman_message = GolemMessageFrame(payload, self.request_id)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                for _i in range(10):
                    send_over_stream(connection=client_socket,
                                     raw_message=middleman_message,
                                     private_key=CONCENT_PRIVATE_KEY)

                unescape_stream_generator = unescape_stream(
                    connection=connection)

                for _i in range(10):
                    raw_message_received = next(unescape_stream_generator)

                    deserialized_message = AbstractFrame.deserialize(
                        raw_message=raw_message_received,
                        public_key=CONCENT_PUBLIC_KEY,
                    )

                    assertpy.assert_that(deserialized_message).is_instance_of(
                        GolemMessageFrame)
                    assertpy.assert_that(
                        deserialized_message.payload).is_instance_of(Ping)
                    assertpy.assert_that(
                        deserialized_message.payload).is_equal_to(payload)

    def test_that_receiving_encoded_message_should_decode_on_the_fly(
            self, unused_tcp_port):
        middleman_message = GolemMessageFrame(Ping(), self.request_id)
        raw_message = append_frame_separator(
            middleman_message.serialize(private_key=CONCENT_PRIVATE_KEY))

        raw_message = raw_message[:10] + ESCAPE_CHARACTER + raw_message[
            len(ESCAPE_CHARACTER) + 10:]
        raw_message_encoded = escape_encode_raw_message(raw_message)

        assert FRAME_SEPARATOR not in raw_message_encoded

        raw_message_encoded = append_frame_separator(raw_message_encoded)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                client_socket.send(raw_message_encoded)
                raw_message_received = next(
                    unescape_stream(connection=connection))

        assertpy_bytes_starts_with(raw_message, raw_message_received)
        assertpy.assert_that(
            len(raw_message_received)).is_greater_than_or_equal_to(
                FRAME_PAYLOAD_STARTING_BYTE)

    def test_that_receiving_wrongly_encoded_message_should_return_none(
            self, unused_tcp_port):
        middleman_message = GolemMessageFrame(Ping(), self.request_id)
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY, )

        raw_message_encoded = escape_encode_raw_message(raw_message)
        raw_message_encoded = raw_message_encoded + ESCAPE_CHARACTER + b'\xff'
        raw_message_encoded = append_frame_separator(raw_message_encoded)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                client_socket.send(raw_message_encoded)
                raw_message_received = next(
                    unescape_stream(connection=connection))

        assertpy.assert_that(raw_message_received).is_none()

    def test_that_exceeding_maximum_frame_length_should_treat_exceeded_frame_as_invalid(
            self, unused_tcp_port):
        first_middleman_message = GolemMessageFrame(Ping(), self.request_id)
        first_raw_message = append_frame_separator(
            escape_encode_raw_message(
                first_middleman_message.serialize(
                    private_key=CONCENT_PRIVATE_KEY)))
        second_middleman_message = AuthenticationChallengeFrame(
            payload=b'',
            request_id=100,
        )
        second_raw_message = append_frame_separator(
            escape_encode_raw_message(
                second_middleman_message.serialize(
                    private_key=CONCENT_PRIVATE_KEY)))

        assert len(first_raw_message) > len(second_raw_message) + 10

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                client_socket.send(first_raw_message)
                client_socket.send(second_raw_message)

                with mock.patch(
                        'middleman_protocol.stream.MAXIMUM_FRAME_LENGTH',
                        len(first_raw_message) - 10):
                    raw_message_received = next(
                        unescape_stream(connection=connection))

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=CONCENT_PUBLIC_KEY,
        )

        assertpy.assert_that(deserialized_message.request_id).is_equal_to(100)
示例#20
0
 def setUp(self, event_loop):
     self.golem_message = Ping()
     self.connection_id = 1
     self.request_id = 777
     self.queue = Queue(loop=event_loop)
     self.response_queue = Queue(loop=event_loop)
示例#21
0
class TestSplitStreamHelperMiddlemanProtocol:

    request_id = 99

    @pytest.mark.parametrize(('middleman_message_type', 'payload'), [
        (GolemMessageFrame, Ping()),
        (ErrorFrame, (111, 'error_message')),
        (AuthenticationChallengeFrame, b'random_bytes'),
        (AuthenticationResponseFrame, b'TODO'),
    ])
    def test_that_receiving_any_message_should_be_handled_correctly(
        self,
        middleman_message_type,
        payload,
        unused_tcp_port,
    ):
        middleman_message = middleman_message_type(payload, self.request_id)
        raw_message = escape_encode_raw_message(
            middleman_message.serialize(private_key=CONCENT_PRIVATE_KEY))
        raw_message_with_separator = append_frame_separator(raw_message)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                client_socket.send(raw_message_with_separator)
                raw_message_received = next(
                    split_stream(connection=connection))

        assertpy.assert_that(raw_message).is_equal_to(raw_message_received)

    def test_that_receiving_a_series_of_messages_should_be_handled_correctly(
            self, unused_tcp_port):
        payload = Ping()
        middleman_message = GolemMessageFrame(payload, self.request_id)
        raw_message = escape_encode_raw_message(
            middleman_message.serialize(private_key=CONCENT_PRIVATE_KEY))
        raw_message_with_separator = append_frame_separator(raw_message)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                for _i in range(10):
                    client_socket.send(raw_message_with_separator)

                split_stream_generator = split_stream(connection=connection)

                for _i in range(10):
                    raw_message_received = next(split_stream_generator)

                    assertpy.assert_that(raw_message).is_equal_to(
                        raw_message_received)

    def test_that_raising_error_in_generator_should_call_close_on_socket(
            self, unused_tcp_port):
        payload = Ping()
        middleman_message = GolemMessageFrame(payload, self.request_id)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                send_over_stream(connection=client_socket,
                                 raw_message=middleman_message,
                                 private_key=CONCENT_PRIVATE_KEY)

                split_stream_generator = split_stream(connection=connection)

                with mock.patch('middleman_protocol.stream.socket.socket.recv',
                                side_effect=Exception()):
                    with mock.patch(
                            'middleman_protocol.stream.socket.socket.close'
                    ) as mock_socket_close:
                        with pytest.raises(Exception):
                            next(split_stream_generator)

                mock_socket_close.assert_called_once()

    def test_that_when_socket_receives_no_bytes_socket_error_is_raised(
            self, unused_tcp_port):  # pylint: disable=no-self-use
        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                # Closing client socket will cause that socket.recv() function will read 0 bytes.
                client_socket.close()
                with pytest.raises(socket.error):
                    next(split_stream(connection=connection))