Example #1
0
    def _unregister_service(self) -> None:
        """
        Unregister service from OEF Service Directory.

        :return: None
        """
        if self._registered_goods_demanded_description is not None:
            msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                             id=DEFAULT_MSG_ID,
                             service_description=self.
                             _registered_goods_demanded_description,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes)
            self._registered_goods_demanded_description = None
        if self._registered_goods_supplied_description is not None:
            msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                             id=DEFAULT_MSG_ID,
                             service_description=self.
                             _registered_goods_supplied_description,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes)
            self._registered_goods_supplied_description = None
Example #2
0
    def decode(self, obj: bytes) -> Message:
        """
        Decode the message.

        :param obj: the bytes object
        :return: the message
        """
        json_msg = json.loads(obj.decode("utf-8"))
        oef_type = OEFMessage.Type(json_msg["type"])
        new_body = copy.copy(json_msg)
        new_body["type"] = oef_type

        if oef_type in {
                OEFMessage.Type.REGISTER_SERVICE,
                OEFMessage.Type.UNREGISTER_SERVICE
        }:
            service_description_bytes = base64.b64decode(
                json_msg["service_description"])
            service_description = pickle.loads(service_description_bytes)
            new_body["service_description"] = service_description
        elif oef_type in {
                OEFMessage.Type.SEARCH_SERVICES, OEFMessage.Type.SEARCH_AGENTS
        }:
            query_bytes = base64.b64decode(json_msg["query"])
            query = pickle.loads(query_bytes)
            new_body["query"] = query
        elif oef_type in {OEFMessage.Type.SEARCH_RESULT}:
            new_body["agents"] = list(json_msg["agents"])
        elif oef_type in {OEFMessage.Type.OEF_ERROR}:
            operation = json_msg["operation"]
            new_body["operation"] = OEFMessage.OEFErrorOperation(
                int(operation))

        oef_message = OEFMessage(oef_type=oef_type, body=new_body)
        return oef_message
Example #3
0
    def on_oef_error(self, answer_id: int,
                     operation: oef.messages.OEFErrorOperation) -> None:
        """
        On oef error event handler.

        :param answer_id: the answer id.
        :param operation: the error operation.
        :return: None
        """
        assert self.in_queue is not None
        assert self.loop is not None
        try:
            operation = OEFMessage.OEFErrorOperation(operation)
        except ValueError:
            operation = OEFMessage.OEFErrorOperation.OTHER

        msg = OEFMessage(oef_type=OEFMessage.Type.OEF_ERROR,
                         id=answer_id,
                         operation=operation)
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=self.public_key,
                            sender=DEFAULT_OEF,
                            protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        asyncio.run_coroutine_threadsafe(self.in_queue.put(envelope),
                                         self.loop).result()
Example #4
0
    def unregister_service(self) -> None:
        """
        Unregister service from OEF Service Directory.

        :return: None
        """
        if self.game_instance.goods_demanded_description is not None:
            msg = OEFMessage(
                oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                id=DEFAULT_MSG_ID,
                service_description=self.game_instance.goods_demanded_description,
                service_id="",
            )
            msg_bytes = OEFSerializer().encode(msg)
            self.mailbox.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.crypto.public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes,
            )
        if self.game_instance.goods_supplied_description is not None:
            msg = OEFMessage(
                oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                id=DEFAULT_MSG_ID,
                service_description=self.game_instance.goods_supplied_description,
                service_id="",
            )
            msg_bytes = OEFSerializer().encode(msg)
            self.mailbox.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.crypto.public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes,
            )
    def test_empty_search_result(self):
        """Test that at the beginning, the search request returns an empty search result."""
        request_id = 1
        query = Query(constraints=[], model=None)

        # build and send the request
        search_services_request = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES, id=request_id, query=query)
        msg_bytes = OEFSerializer().encode(search_services_request)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        self.multiplexer.put(envelope)

        # check the result
        response_envelope = self.multiplexer.get(block=True, timeout=2.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.to == self.public_key_1
        assert response_envelope.sender == DEFAULT_OEF
        search_result = OEFSerializer().decode(response_envelope.message)
        assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT
        assert search_result.get("agents") == []

        # build and send the request
        search_agents_request = OEFMessage(oef_type=OEFMessage.Type.SEARCH_AGENTS, id=request_id, query=query)
        msg_bytes = OEFSerializer().encode(search_agents_request)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        self.multiplexer.put(envelope)

        # check the result
        response_envelope = self.multiplexer.get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.sender == DEFAULT_OEF
        search_result = OEFSerializer().decode(response_envelope.message)
        assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT
        assert search_result.get("agents") == []
Example #6
0
    def _unregister_service(self) -> None:
        """
        Unregister service from OEF Service Directory.

        :return: None
        """
        registration = cast(Registration, self.context.registration)

        if registration.registered_goods_demanded_description is not None:
            oef_msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                                 id=registration.get_next_id(),
                                 service_description=registration.
                                 registered_goods_demanded_description,
                                 service_id="")
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(oef_msg))
            registration.registered_goods_demanded_description = None

        if registration.registered_goods_supplied_description is not None:
            oef_msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                                 id=registration.get_next_id(),
                                 service_description=registration.
                                 registered_goods_supplied_description,
                                 service_id="")
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(oef_msg))
            registration.registered_goods_supplied_description = None
        def test_register_service(self):
            """Test that a register service request works correctly."""
            foo_datamodel = DataModel(
                "foo", [Attribute("bar", int, True, "A bar attribute.")])
            desc = Description({"bar": 1}, data_model=foo_datamodel)
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE,
                             id=1,
                             service_description=desc,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.mailbox1.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.crypto1.public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes)

            search_request = OEFMessage(
                oef_type=OEFMessage.Type.SEARCH_SERVICES,
                id=2,
                query=Query([Constraint("bar", ConstraintType("==", 1))],
                            model=foo_datamodel))
            self.mailbox1.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.crypto1.public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(search_request))
            envelope = self.mailbox1.inbox.get(block=True, timeout=5.0)
            search_result = OEFSerializer().decode(envelope.message)
            assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT
            assert search_result.get("id") == 2
            assert search_result.get("agents") == [self.crypto1.public_key]
Example #8
0
    def register_service(self) -> None:
        """
        Register to the OEF Service Directory.

        In particular, register
            - as a seller, listing the goods supplied, or
            - as a buyer, listing the goods demanded, or
            - as both.

        :return: None
        """
        if self.game_instance.strategy.is_registering_as_seller:
            logger.debug("[{}]: Updating service directory as seller with goods supplied.".format(self.agent_name))
            goods_supplied_description = self.game_instance.get_service_description(is_supply=True)
            self.game_instance.goods_supplied_description = goods_supplied_description
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=DEFAULT_MSG_ID, service_description=goods_supplied_description, service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.mailbox.outbox.put_message(to=DEFAULT_OEF, sender=self.crypto.public_key, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        if self.game_instance.strategy.is_registering_as_buyer:
            logger.debug("[{}]: Updating service directory as buyer with goods demanded.".format(self.agent_name))
            goods_demanded_description = self.game_instance.get_service_description(is_supply=False)
            self.game_instance.goods_demanded_description = goods_demanded_description
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=DEFAULT_MSG_ID, service_description=goods_demanded_description, service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.mailbox.outbox.put_message(to=DEFAULT_OEF, sender=self.crypto.public_key, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
async def test_send_oef_message(network_node):
    """Test the send oef message."""
    private_key_pem_path = os.path.join(CUR_PATH, "data", "priv.pem")
    wallet = Wallet({'default': private_key_pem_path})
    public_key = wallet.public_keys['default']
    oef_connection = OEFConnection(public_key=public_key,
                                   oef_addr="127.0.0.1",
                                   oef_port=10000)
    oef_connection.loop = asyncio.get_event_loop()
    await oef_connection.connect()

    msg = OEFMessage(oef_type=OEFMessage.Type.OEF_ERROR,
                     id=0,
                     operation=OEFMessage.OEFErrorOperation.SEARCH_AGENTS)
    msg_bytes = OEFSerializer().encode(msg)
    envelope = Envelope(to=DEFAULT_OEF,
                        sender=public_key,
                        protocol_id=OEFMessage.protocol_id,
                        message=msg_bytes)
    with pytest.raises(ValueError):
        await oef_connection.send(envelope)

    data_model = DataModel("foobar", attributes=[])
    query = Query(constraints=[], model=data_model)

    msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_AGENTS, id=0, query=query)
    msg_bytes = OEFSerializer().encode(msg)
    envelope = Envelope(to="recipient",
                        sender=public_key,
                        protocol_id=OEFMessage.protocol_id,
                        message=msg_bytes)
    await oef_connection.send(envelope)
    await oef_connection.disconnect()
    def test_unregister_service_result(self):
        """Test that at the beginning, the search request returns an empty search result."""
        data_model = DataModel("foobar", attributes=[])
        service_description = Description({"foo": 1, "bar": "baz"}, data_model=data_model)
        msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE, id=0, service_description=service_description,
                         service_id="Test_service")
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)

        # check the result
        response_envelope = self.multiplexer1.get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.sender == DEFAULT_OEF
        result = OEFSerializer().decode(response_envelope.message)
        assert result.get("type") == OEFMessage.Type.OEF_ERROR

        msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=0, service_description=service_description,
                         service_id="Test_Service")
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)

        # Search for the register agent
        msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_AGENTS, id=0, query=Query([Constraint("foo", ConstraintType("==", 1))]))
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)
        # check the result
        response_envelope = self.multiplexer1.get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.sender == DEFAULT_OEF
        result = OEFSerializer().decode(response_envelope.message)
        assert result.get("type") == OEFMessage.Type.SEARCH_RESULT
        assert len(result.get("agents")) == 1

        # unregister the service
        data_model = DataModel("foobar", attributes=[])
        service_description = Description({"foo": 1, "bar": "baz"}, data_model=data_model)
        msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE, id=0, service_description=service_description,
                         service_id="Test_service")
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)

        # the same query returns empty
        # Search for the register agent
        msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_AGENTS, id=0, query=Query([Constraint("foo", ConstraintType("==", 1))]))
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)
        # check the result
        response_envelope = self.multiplexer1.get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.sender == DEFAULT_OEF
        result = OEFSerializer().decode(response_envelope.message)
        assert result.get("type") == OEFMessage.Type.SEARCH_RESULT
        assert len(result.get("agents")) == 0
Example #11
0
    def _search_services(self) -> None:
        """
        Search on OEF Service Directory.

        In particular, search
            - for sellers and their supply, or
            - for buyers and their demand, or
            - for both.

        :return: None
        """
        strategy = cast(Strategy, self.context.strategy)
        search = cast(Search, self.context.search)

        if strategy.is_searching_for_sellers:
            query = strategy.get_own_services_query(
                is_searching_for_sellers=True)
            if query is None:
                logger.warning(
                    "[{}]: Not searching the OEF for sellers because the agent demands no goods."
                    .format(self.context.agent_name))
                return None
            else:
                search_id = search.get_next_id(is_searching_for_sellers=True)
                logger.info(
                    "[{}]: Searching for sellers which match the demand of the agent, search_id={}."
                    .format(self.context.agent_name, search_id))
                oef_msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES,
                                     id=search_id,
                                     query=query)
                self.context.outbox.put_message(
                    to=DEFAULT_OEF,
                    sender=self.context.agent_public_key,
                    protocol_id=OEFMessage.protocol_id,
                    message=OEFSerializer().encode(oef_msg))

        if strategy.is_searching_for_buyers:
            query = strategy.get_own_services_query(
                is_searching_for_sellers=False)
            if query is None:
                logger.warning(
                    "[{}]: Not searching the OEF for buyers because the agent supplies no goods."
                    .format(self.context.agent_name))
                return None
            else:
                search_id = search.get_next_id(is_searching_for_sellers=False)
                logger.info(
                    "[{}]: Searching for buyers which match the supply of the agent, search_id={}."
                    .format(self.context.agent_name, search_id))
                oef_msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES,
                                     id=search_id,
                                     query=query)
                self.context.outbox.put_message(
                    to=DEFAULT_OEF,
                    sender=self.context.agent_public_key,
                    protocol_id=OEFMessage.protocol_id,
                    message=OEFSerializer().encode(oef_msg))
Example #12
0
    def _on_oef_error(self, oef_error: OEFMessage) -> None:
        """
        Handle an OEF error message.

        :param oef_error: the oef error

        :return: None
        """
        logger.error("[{}]: Received OEF error: answer_id={}, operation={}"
                     .format(self.context.agent_name, oef_error.get("id"), oef_error.get("operation")))
Example #13
0
    def _on_dialogue_error(self, dialogue_error: OEFMessage) -> None:
        """
        Handle a dialogue error message.

        :param dialogue_error: the dialogue error message

        :return: None
        """
        logger.error("[{}]: Received Dialogue error: answer_id={}, dialogue_id={}, origin={}"
                     .format(self.context.agent_name, dialogue_error.get("id"), dialogue_error.get("dialogue_id"), dialogue_error.get("origin")))
Example #14
0
        def setup_class(cls):
            """
            Set the test up.

            Steps:
            - Register a service
            - Check that the registration worked.
            """
            cls.crypto1 = DefaultCrypto()
            cls.connection = OEFConnection(cls.crypto1.public_key,
                                           oef_addr="127.0.0.1",
                                           oef_port=10000)
            cls.multiplexer = Multiplexer([cls.connection])
            cls.multiplexer.connect()

            cls.request_id = 1
            cls.foo_datamodel = DataModel(
                "foo", [Attribute("bar", int, True, "A bar attribute.")])
            cls.desc = Description({"bar": 1}, data_model=cls.foo_datamodel)
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE,
                             id=cls.request_id,
                             service_description=cls.desc,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            cls.multiplexer.put(
                Envelope(to=DEFAULT_OEF,
                         sender=cls.crypto1.public_key,
                         protocol_id=OEFMessage.protocol_id,
                         message=msg_bytes))

            time.sleep(1.0)

            cls.request_id += 1
            search_request = OEFMessage(
                oef_type=OEFMessage.Type.SEARCH_SERVICES,
                id=cls.request_id,
                query=Query([Constraint("bar", ConstraintType("==", 1))],
                            model=cls.foo_datamodel))
            cls.multiplexer.put(
                Envelope(to=DEFAULT_OEF,
                         sender=cls.crypto1.public_key,
                         protocol_id=OEFMessage.protocol_id,
                         message=OEFSerializer().encode(search_request)))
            envelope = cls.multiplexer.get(block=True, timeout=5.0)
            search_result = OEFSerializer().decode(envelope.message)
            assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT
            assert search_result.get("id") == cls.request_id
            if search_result.get("agents") != [cls.crypto1.public_key]:
                logger.warning(
                    'search_result.get("agents") != [self.crypto1.public_key] FAILED in test_oef/test_communication.py'
                )
Example #15
0
    def _register_service(self) -> None:
        """
        Register to the OEF Service Directory.

        In particular, register
            - as a seller, listing the goods supplied, or
            - as a buyer, listing the goods demanded, or
            - as both.

        :return: None
        """
        strategy = cast(Strategy, self.context.strategy)
        transactions = cast(Transactions, self.context.transactions)
        if strategy.is_registering_as_seller:
            logger.debug(
                "[{}]: Updating service directory as seller with goods supplied."
                .format(self.context.agent_name))
            ownership_state_after_locks = transactions.ownership_state_after_locks(
                self.context.ownership_state, is_seller=True)
            goods_supplied_description = strategy.get_own_service_description(
                ownership_state_after_locks, is_supply=True)
            self._registered_goods_supplied_description = goods_supplied_description
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE,
                             id=DEFAULT_MSG_ID,
                             service_description=goods_supplied_description,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes)
        if strategy.is_registering_as_buyer:
            logger.debug(
                "[{}]: Updating service directory as buyer with goods demanded."
                .format(self.context.agent_name))
            ownership_state_after_locks = transactions.ownership_state_after_locks(
                self.context.ownership_state, is_seller=False)
            goods_demanded_description = strategy.get_own_service_description(
                ownership_state_after_locks, is_supply=False)
            self._registered_goods_demanded_description = goods_demanded_description
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE,
                             id=DEFAULT_MSG_ID,
                             service_description=goods_demanded_description,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes)
Example #16
0
def test_oef_message_consistency():
    """Tests the consistency of an OEFMessage."""
    foo_datamodel = DataModel(
        "foo", [Attribute("bar", int, True, "A bar attribute.")])
    msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_AGENTS,
                     id=2,
                     query=Query([Constraint("bar", ConstraintType("==", 1))],
                                 model=foo_datamodel))
    assert msg.check_consistency(), "We expect the consistency to return TRUE"
    with mock.patch("aea.protocols.oef.message.OEFMessage.Type")\
            as mock_type_enum:
        mock_type_enum.SEARCH_AGENTS.value = "unknown"
        assert not msg.check_consistency(),\
            "Expect the consistency to return False"
    def test_search_agent(self):
        """Test the registered agents, we will not find any."""
        data_model = DataModel("foobar", attributes=[])
        agent_description = Description({"foo": 1, "bar": "baz"}, data_model=data_model)
        query = Query(constraints=[], model=data_model)

        # Register an agent
        msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_AGENT, id=0, agent_description=agent_description,
                         agent_id="Test_agent")
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)

        time.sleep(0.1)

        # Search for the register agent
        msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_AGENTS, id=0, query=query)
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_2, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer2.put(envelope)

        # check the result
        response_envelope = self.multiplexer2.get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.sender == DEFAULT_OEF
        result = OEFSerializer().decode(response_envelope.message)
        assert len(result.get("agents")) == 1, "There are registered agents!"

        # Send unregister message.
        msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_AGENT, id=0, agent_description=agent_description,
                         agent_id="Test_agent")
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)

        time.sleep(0.1)

        # Trigger error message.
        msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_AGENT, id=0, agent_description=agent_description,
                         agent_id="Unknown_Agent")
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)

        # check the result
        response_envelope = self.multiplexer1.get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.sender == DEFAULT_OEF
        result = OEFSerializer().decode(response_envelope.message)
        assert result.get("type") == OEFMessage.Type.OEF_ERROR
Example #18
0
    def _register_service(self) -> None:
        """
        Register to the OEF Service Directory.

        In particular, register
            - as a seller, listing the goods supplied, or
            - as a buyer, listing the goods demanded, or
            - as both.

        :return: None
        """
        registration = cast(Registration, self.context.registration)
        strategy = cast(Strategy, self.context.strategy)

        if strategy.is_registering_as_seller:
            logger.debug(
                "[{}]: Updating service directory as seller with goods supplied."
                .format(self.context.agent_name))
            goods_supplied_description = strategy.get_own_service_description(
                is_supply=True)
            registration.registered_goods_supplied_description = goods_supplied_description
            oef_msg = OEFMessage(
                oef_type=OEFMessage.Type.REGISTER_SERVICE,
                id=registration.get_next_id(),
                service_description=goods_supplied_description,
                service_id="")
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(oef_msg))

        if strategy.is_registering_as_buyer:
            logger.debug(
                "[{}]: Updating service directory as buyer with goods demanded."
                .format(self.context.agent_name))
            goods_demanded_description = strategy.get_own_service_description(
                is_supply=False)
            registration.registered_goods_demanded_description = goods_demanded_description
            oef_msg = OEFMessage(
                oef_type=OEFMessage.Type.REGISTER_SERVICE,
                id=registration.get_next_id(),
                service_description=goods_demanded_description,
                service_id="")
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(oef_msg))
Example #19
0
def test_oef_message_OEFError():
    """Tests the OEF_ERROR type of message."""
    msg = OEFMessage(oef_type=OEFMessage.Type.OEF_ERROR,
                     id=0,
                     operation=OEFMessage.OEFErrorOperation.SEARCH_AGENTS)

    assert OEFMessage(oef_type=OEFMessage.Type.OEF_ERROR, id=0,
                      operation=OEFMessage.OEFErrorOperation.SEARCH_AGENTS),\
        "Expects an oef message Error!"
    msg_bytes = OEFSerializer().encode(msg)
    assert len(msg_bytes) > 0,\
        "Expects the length of bytes not to be Empty"
    deserialized_msg = OEFSerializer().decode(msg_bytes)
    assert msg == deserialized_msg,\
        "Expected the deserialized_msg to me equals to msg"
Example #20
0
    def setup_class(cls):
        """Set up the test."""
        cls.node = LocalNode()

        cls.public_key_1 = "mailbox1"
        cls.mailbox1 = MailBox(OEFLocalConnection(cls.public_key_1, cls.node))

        cls.mailbox1.connect()

        # register a service.
        request_id = 1
        service_id = ''
        cls.data_model = DataModel("foobar", attributes=[])
        service_description = Description({
            "foo": 1,
            "bar": "baz"
        },
                                          data_model=cls.data_model)
        register_service_request = OEFMessage(
            oef_type=OEFMessage.Type.REGISTER_SERVICE,
            id=request_id,
            service_description=service_description,
            service_id=service_id)
        msg_bytes = OEFSerializer().encode(register_service_request)
        envelope = Envelope(to=DEFAULT_OEF,
                            sender=cls.public_key_1,
                            protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        cls.mailbox1.send(envelope)
Example #21
0
    def test_not_empty_search_result(self):
        """Test that the search result contains one entry after a successful registration."""
        request_id = 1
        query = Query(constraints=[], model=self.data_model)

        # build and send the request
        search_services_request = OEFMessage(
            oef_type=OEFMessage.Type.SEARCH_SERVICES,
            id=request_id,
            query=query)
        msg_bytes = OEFSerializer().encode(search_services_request)
        envelope = Envelope(to=DEFAULT_OEF,
                            sender=self.public_key_1,
                            protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        self.mailbox1.send(envelope)

        # check the result
        response_envelope = self.mailbox1.inbox.get(block=True, timeout=2.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.to == self.public_key_1
        assert response_envelope.sender == DEFAULT_OEF
        search_result = OEFSerializer().decode(response_envelope.message)
        assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT
        assert search_result.get("agents") == [self.public_key_1]
        def test_search_services_with_query_with_model(self):
            """Test that a search services request can be sent correctly.

            In this test, the query has a simple data model.
            """
            request_id = 2
            data_model = DataModel("foobar", [Attribute("foo", str, True)])
            search_query = Query(
                [Constraint("foo", ConstraintType("==", "bar"))],
                model=data_model)
            search_request = OEFMessage(
                oef_type=OEFMessage.Type.SEARCH_SERVICES,
                id=request_id,
                query=search_query)
            self.mailbox1.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.crypto1.public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(search_request))

            envelope = self.mailbox1.inbox.get(block=True, timeout=5.0)
            search_result = OEFSerializer().decode(envelope.message)
            assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT
            assert search_result.get("id") == request_id
            assert search_result.get("agents") == []
Example #23
0
    def search_for_tac(self) -> None:
        """
        Search for active TAC Controller.

        We assume that the controller is registered as a service with the 'tac' data model
        and with an attribute version = expected_version_id.

        :return: None
        """
        query = Query(
            [Constraint("version", GtEq(self.game_instance.expected_version_id))]
        )
        search_id = self.game_instance.search.get_next_id()
        self.game_instance.search.ids_for_tac.add(search_id)

        msg = OEFMessage(
            oef_type=OEFMessage.Type.SEARCH_SERVICES, id=search_id, query=query
        )
        msg_bytes = OEFSerializer().encode(msg)
        self.mailbox.outbox.put_message(
            to=DEFAULT_OEF,
            sender=self.crypto.public_key,
            protocol_id=OEFMessage.protocol_id,
            message=msg_bytes,
        )
Example #24
0
    def encode(self, msg: Message) -> bytes:
        """
        Decode the message.

        :param msg: the message object
        :return: the bytes
        """
        oef_type = OEFMessage.Type(msg.get("type"))
        new_body = copy.copy(msg.body)
        new_body["type"] = oef_type.value

        if oef_type in {OEFMessage.Type.REGISTER_SERVICE, OEFMessage.Type.UNREGISTER_SERVICE}:
            service_description = msg.body["service_description"]  # type: Description
            service_description_bytes = base64.b64encode(pickle.dumps(service_description)).decode("utf-8")
            new_body["service_description"] = service_description_bytes
        elif oef_type in {OEFMessage.Type.REGISTER_AGENT, OEFMessage.Type.UNREGISTER_AGENT}:
            agent_description = msg.body["agent_description"]  # type: Description
            agent_description_bytes = base64.b64encode(pickle.dumps(agent_description)).decode("utf-8")
            new_body["agent_description"] = agent_description_bytes
        elif oef_type in {OEFMessage.Type.SEARCH_SERVICES, OEFMessage.Type.SEARCH_AGENTS}:
            query = msg.body["query"]  # type: Query
            query_bytes = base64.b64encode(pickle.dumps(query)).decode("utf-8")
            new_body["query"] = query_bytes
        elif oef_type in {OEFMessage.Type.SEARCH_RESULT}:
            # we need this cast because the "agents" field might contains
            # the Protobuf type "RepeatedScalarContainer", which is not JSON serializable.
            new_body["agents"] = list(msg.body["agents"])
        elif oef_type in {OEFMessage.Type.OEF_ERROR}:
            operation = msg.body["operation"]
            new_body["operation"] = str(operation)

        oef_message_bytes = json.dumps(new_body).encode("utf-8")
        return oef_message_bytes
Example #25
0
def test_oef_message_DialogeError():
    """Tests the OEFMEssage of type DialogueError."""
    assert OEFMessage(oef_type=OEFMessage.Type.DIALOGUE_ERROR,
                      id=0,
                      dialogue_id=1,
                      origin="myKey"),\
        "Could not create the message of type DialogueError"
Example #26
0
    def handle_envelope(self, envelope: Envelope) -> None:
        """
        Implement the reaction to an envelope.

        :param envelope: the envelope
        :return: None
        """
        msg = OEFSerializer().decode(envelope.message)
        msg_type = OEFMessage.Type(msg.get("type"))

        if msg_type is OEFMessage.Type.SEARCH_RESULT:
            agents = cast(List[str], msg.get("agents"))
            logger.info("[{}]: found agents={}".format(self.context.agent_name,
                                                       agents))
            for agent in agents:
                msg = FIPAMessage(message_id=STARTING_MESSAGE_ID,
                                  dialogue_id=self.dialogue_id,
                                  performative=FIPAMessage.Performative.CFP,
                                  target=STARTING_TARGET_ID,
                                  query=None)
                self.dialogue_id += 1
                self.context.outbox.put_message(
                    to=agent,
                    sender=self.context.agent_public_key,
                    protocol_id=FIPAMessage.protocol_id,
                    message=FIPASerializer().encode(msg))
Example #27
0
    def handle(self, message: Message, sender: str) -> None:
        """
        Implement the reaction to a message.

        :param message: the message
        :param sender: the sender
        :return: None
        """
        # convenience representations
        oef_msg = cast(OEFMessage, message)
        oef_msg_type = OEFMessage.Type(oef_msg.get("type"))

        if oef_msg_type is OEFMessage.Type.SEARCH_RESULT:
            agents = cast(List[str], oef_msg.get("agents"))
            search_id = cast(int, oef_msg.get("id"))
            search = cast(Search, self.context.search)
            if self.context.agent_public_key in agents:
                agents.remove(self.context.agent_public_key)
            if search_id in search.ids_for_sellers:
                self._handle_search(agents,
                                    search_id,
                                    is_searching_for_sellers=True)
            elif search_id in search.ids_for_buyers:
                self._handle_search(agents,
                                    search_id,
                                    is_searching_for_sellers=False)
Example #28
0
    async def _handle_oef_message(self, envelope: Envelope) -> None:
        """Handle oef messages.

        :param envelope: the envelope
        :return: None
        """
        oef_message = OEFSerializer().decode(envelope.message)
        sender = envelope.sender
        request_id = cast(int, oef_message.get("id"))
        oef_type = OEFMessage.Type(oef_message.get("type"))
        if oef_type == OEFMessage.Type.REGISTER_SERVICE:
            await self._register_service(
                sender,
                cast(Description, oef_message.get("service_description")))
        elif oef_type == OEFMessage.Type.REGISTER_AGENT:
            await self._register_agent(
                sender, cast(Description,
                             oef_message.get("agent_description")))
        elif oef_type == OEFMessage.Type.UNREGISTER_SERVICE:
            await self._unregister_service(
                sender, request_id,
                cast(Description, oef_message.get("service_description")))
        elif oef_type == OEFMessage.Type.UNREGISTER_AGENT:
            await self._unregister_agent(
                sender, request_id,
                cast(Description, oef_message.get("agent_description")))
        elif oef_type == OEFMessage.Type.SEARCH_AGENTS:
            await self._search_agents(sender, request_id,
                                      cast(Query, oef_message.get("query")))
        elif oef_type == OEFMessage.Type.SEARCH_SERVICES:
            await self._search_services(sender, request_id,
                                        cast(Query, oef_message.get("query")))
        else:
            # request not recognized
            pass
Example #29
0
    async def _unregister_agent(self, public_key: str, msg_id: int,
                                agent_description: Description) -> None:
        """
        Unregister an agent.

        :param agent_description:
        :param public_key: the public key of the service agent to be unregistered.
        :param msg_id: the message id of the request.
        :return: None
        """
        async with self._lock:
            if public_key not in self.agents:
                msg = OEFMessage(
                    oef_type=OEFMessage.Type.OEF_ERROR,
                    id=msg_id,
                    operation=OEFMessage.OEFErrorOperation.UNREGISTER_AGENT)
                msg_bytes = OEFSerializer().encode(msg)
                envelope = Envelope(to=public_key,
                                    sender=DEFAULT_OEF,
                                    protocol_id=OEFMessage.protocol_id,
                                    message=msg_bytes)
                await self._send(envelope)
            else:
                self.agents[public_key].remove(agent_description)
                if len(self.agents[public_key]) == 0:
                    self.agents.pop(public_key)
Example #30
0
    async def _search_services(self, public_key: str, search_id: int,
                               query: Query) -> None:
        """
        Search the agents in the local Service Directory, and send back the result.

        This is actually a dummy search, it will return all the registered agents with the specified data model.
        If the data model is not specified, it will return all the agents.

        :param public_key: the source of the search request.
        :param search_id: the search identifier associated with the search request.
        :param query: the query that constitutes the search.
        :return: None
        """
        result = []  # type: List[str]
        if query.model is None:
            result = list(set(self.services.keys()))
        else:
            for agent_public_key, descriptions in self.services.items():
                for description in descriptions:
                    if description.data_model == query.model:
                        result.append(agent_public_key)

        msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_RESULT,
                         id=search_id,
                         agents=sorted(set(result)))
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=public_key,
                            sender=DEFAULT_OEF,
                            protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        await self._send(envelope)