Example #1
0
void TrustedConnectionCreatorintegration::test_external_op_puppet_nonexistant()
{
    // Dispatching a Talk external op from the creator, to the creator should
    // result in it being passed directly to the normal op dispatch,
    // shortcutting the world.

    m_creator->m_externalMind = new ExternalMind(*m_creator);
    m_creator->m_externalMind->linkUp(m_connection);

    Entity * other = new Entity(compose("%1", m_id_counter), m_id_counter++);
    other->setType(m_creatorType);
    m_server->m_world.addEntity(other);

    Atlas::Objects::Operation::Talk op;
    op->setFrom(m_creator->getId());
    op->setTo(compose("%1", m_id_counter++));

    m_connection->externalOperation(op, *m_connection);

    // Operation should be via world dispatch, as if it was from the Entity
    // we are puppeting.
    ASSERT_TRUE(m_Link_send_sent.isValid());
    ASSERT_EQUAL(m_Link_send_sent->getParents().front(),
                 "unseen");
    ASSERT_TRUE(!m_Link_send_sent->isDefaultTo());
    ASSERT_EQUAL(m_Link_send_sent->getTo(), m_creator->getId());
}
Example #2
0
void ConnectionCharacterintegration::test_connected()
{
    // Dispatching an external op from the character should have no effect
    // if the external mind is already in place.

    m_character->linkExternal(m_connection);

    ASSERT_NOT_NULL(m_character->m_externalMind);
    ExternalMind * em =
          dynamic_cast<ExternalMind*>(m_character->m_externalMind);
    ASSERT_NOT_NULL(em);
    ASSERT_TRUE(em->isLinked());
    ASSERT_TRUE(em->isLinkedTo(m_connection));

    Router * saved_em = m_character->m_externalMind;

    RootOperation op;
    op->setFrom(m_character->getId());

    m_connection->externalOperation(op, *m_connection);

    ASSERT_TRUE(!m_Link_send_sent.isValid());
    ASSERT_NOT_EQUAL(m_logEvent_logged, TAKE_CHAR);
    ASSERT_NOT_NULL(m_character->m_externalMind);
    ASSERT_EQUAL(m_character->m_externalMind, saved_em);
    em = dynamic_cast<ExternalMind*>(m_character->m_externalMind);
    ASSERT_NOT_NULL(em);
    ASSERT_TRUE(em->isLinked());
    ASSERT_TRUE(em->isLinkedTo(m_connection));
}
Example #3
0
void TrustedConnectionCreatorintegration::test_external_op_puppet()
{
    // Dispatching a Talk external op from the creator, to the creator should
    // result in it being passed directly to the normal op dispatch,
    // shortcutting the world.

    m_creator->m_externalMind = new ExternalMind(*m_creator);
    m_creator->m_externalMind->linkUp(m_connection);

    Entity * other = new Entity(compose("%1", m_id_counter), m_id_counter++);
    other->setType(m_creatorType);
    m_server->m_world.addEntity(other);

    Atlas::Objects::Operation::Talk op;
    op->setFrom(m_creator->getId());
    op->setTo(other->getId());

    m_connection->externalOperation(op, *m_connection);

    // Operation should be via world dispatch, as if it was from the Entity
    // we are puppeting.
    ASSERT_TRUE(m_BaseWorld_message_called.isValid());
    ASSERT_EQUAL(m_BaseWorld_message_called->getClassNo(),
                 Atlas::Objects::Operation::TALK_NO);
    ASSERT_TRUE(!m_BaseWorld_message_called->isDefaultTo());
    ASSERT_EQUAL(m_BaseWorld_message_called->getTo(), other->getId());
    ASSERT_NOT_NULL(m_BaseWorld_message_called_from);
    ASSERT_EQUAL(m_BaseWorld_message_called_from, other);
}
Example #4
0
void World::RelayOperation(const Operation & op, OpVector & res)
{
    //A Relay operation with refno sent to ourselves signals that we should prune
    //our registered relays in m_relays. This is a feature to allow for a timeout; if
    //no Relay has been received from the destination Entity after a certain period
    //we'll shut down the relay link.
    if (op->getTo() == getId() && op->getFrom() == getId() && !op->isDefaultRefno()) {
        auto I = m_relays.find(op->getRefno());
        if (I != m_relays.end()) {

            //Send an empty operation to signal that the relay has expired.
            I->second.callback(Operation(), I->second.entityId);
            m_relays.erase(I);
        }
    } else {
        if (op->getArgs().empty()) {
            log(ERROR, "World::RelayOperation no args.");
            return;
        }
        Operation relayedOp = Atlas::Objects::smart_dynamic_cast<Operation>(
                op->getArgs().front());

        if (!relayedOp.isValid()) {
            log(ERROR,
                    "World::RelayOperation first arg is not an operation.");
            return;
        }


        //If a relay op has a refno, it's a response to a Relay op previously sent out to another
        //entity, and we should signal that we have an incoming relayed op.
        if (!op->isDefaultRefno()) {
            //Note that the relayed op should be considered untrusted in this case, as it has originated
            //from a random entity or its mind.
            auto I = m_relays.find(op->getRefno());
            if (I == m_relays.end()) {
                log(WARNING,
                        "World::RelayOperation could not find registrered Relay with refno.");
                return;
            }

            //Make sure that this op really comes from the entity the original Relay op was sent to.
            if (op->getFrom() != I->second.entityId) {
                log(WARNING,
                        "World::RelayOperation got relay op with mismatching 'from'.");
                return;
            }

            //Get the relayed operation and call the callback.
            I->second.callback(relayedOp, I->second.entityId);

            m_relays.erase(I);

        } else {
            //Send it on to the basic Entity relay mechanism
            Entity::RelayOperation(op, res);
        }
    }

}
Example #5
0
/// \brief Handle a relay operation
void Entity::RelayOperation(const Operation & op, OpVector & res)
{
    if (op->getArgs().empty()) {
        log(ERROR, "Entity::RelayOperation no args.");
        return;
    }
    Operation relayedOp = Atlas::Objects::smart_dynamic_cast<Operation>(
            op->getArgs().front());

    if (!relayedOp.isValid()) {
        log(ERROR,
                "Entity::RelayOperation first arg is not an operation.");
        return;
    }

    if (op->isDefaultSerialno()) {
        log(ERROR, "Entity::RelayOperation no serial number.");
        return;
    }

    //Add a sight of the operation
    Sight sight;
    sight->setArgs1(relayedOp);

    Atlas::Objects::Operation::Generic responseOp;
    responseOp->setType("relay", Atlas::Objects::Operation::RELAY_NO);
    responseOp->setArgs1(sight);
    responseOp->setTo(op->getFrom());
    res.push_back(responseOp);

    //Make sure that the contained op is addressed to the entity
    relayedOp->setTo(getId());
    operation(relayedOp, res);

}
Example #6
0
void ConnectionCharacterintegration::test_external_op()
{
    // Dispatching a Talk external op from the character should result in
    // it being passed on to the world.

    m_character->linkExternal(m_connection);

    Atlas::Objects::Operation::Talk op;
    op->setFrom(m_character->getId());

    m_connection->externalOperation(op, *m_connection);

    // BaseWorld::message should have been called from Enitty::sendWorld
    // with the Talk operation, modified to have TO set to the character.
    ASSERT_TRUE(m_BaseWorld_message_called.isValid());
    ASSERT_EQUAL(m_BaseWorld_message_called->getClassNo(),
                 Atlas::Objects::Operation::TALK_NO);
    ASSERT_TRUE(!m_BaseWorld_message_called->isDefaultTo());
    ASSERT_EQUAL(m_BaseWorld_message_called->getTo(), m_character->getId());
    ASSERT_NOT_NULL(m_BaseWorld_message_called_from);
    ASSERT_EQUAL(m_BaseWorld_message_called_from, m_character);
}
/// \brief Add an operation to the ordered op queue.
///
/// Any time adjustment required is made to the operation, and it
/// is added to the apropriate place in the chronologically ordered
/// queue. The From attribute of the operation is set to the id of
/// the entity that is responsible for adding the operation to the
/// queue.
void OperationsDispatcher::addOperationToQueue(const Operation & op, LocatedEntity & ent)
{
    assert(op.isValid());
    assert(op->getFrom() != "cheat");

    m_operation_queues_dirty = true;
    op->setFrom(ent.getId());
    if (!op->hasAttrFlag(Atlas::Objects::Operation::FUTURE_SECONDS_FLAG)) {
        op->setSeconds(getTime());
        m_immediateQueue.push(OpQueEntry(op, ent));
        return;
    }
    double t = getTime() + (op->getFutureSeconds() * consts::time_multiplier);
    op->setSeconds(t);
    op->setFutureSeconds(0.);
    m_operationQueue.push(OpQueEntry(op, ent));
    if (debug_flag) {
        std::cout << "WorldRouter::addOperationToQueue {" << std::endl;
        debug_dump(op, std::cout);
        std::cout << "}" << std::endl << std::flush;
    }
}
Example #8
0
void ConnectionCharacterintegration::test_connect_up()
{
    // Dispatching an external op from the character should cause it to
    // get connected up with an external mind

    RootOperation op;
    op->setFrom(m_character->getId());

    ASSERT_NULL(m_character->m_externalMind);

    m_connection->externalOperation(op, *m_connection);

    ASSERT_NOT_NULL(m_character->m_externalMind);
    ExternalMind * em =
          dynamic_cast<ExternalMind*>(m_character->m_externalMind);
    ASSERT_NOT_NULL(em);
    ASSERT_TRUE(em->isLinked());
    ASSERT_TRUE(em->isLinkedTo(m_connection));
    ASSERT_TRUE(m_Link_send_sent.isValid());
    ASSERT_EQUAL(m_Link_send_sent->getClassNo(),
                 Atlas::Objects::Operation::INFO_NO);
    ASSERT_EQUAL(m_logEvent_logged, TAKE_CHAR);
}
Example #9
0
void TrustedConnectionCreatorintegration::test_external_op_override()
{
    // Dispatching a Talk external op from the creator should result in
    // it being passed on to the world, exactly as if this was a Character
    // except that we assume that Creator was set up linked.

    m_creator->m_externalMind = new ExternalMind(*m_creator);
    m_creator->m_externalMind->linkUp(m_connection);

    Atlas::Objects::Operation::Talk op;
    op->setFrom(m_creator->getId());
    op->setTo(m_creator->getId());

    m_connection->externalOperation(op, *m_connection);

    // The operation should have been passed to Entity::callOperation for
    // dispatch, completely unfiltered.
    ASSERT_TRUE(m_Entity_callOperation_called.isValid());
    ASSERT_EQUAL(m_Entity_callOperation_called->getClassNo(),
                 Atlas::Objects::Operation::TALK_NO);
    ASSERT_TRUE(!m_Entity_callOperation_called->isDefaultTo());
    ASSERT_EQUAL(m_Entity_callOperation_called->getTo(), m_creator->getId());
}
Example #10
0
void ConnectionCharacterintegration::test_unlinked()
{
    // Dispatching an external op from the character if the external mind is
    // already in place, but is not linked to a connection should link it
    // back up.

    m_character->linkExternal(m_connection);

    ASSERT_NOT_NULL(m_character->m_externalMind);
    ExternalMind * em =
          dynamic_cast<ExternalMind*>(m_character->m_externalMind);
    ASSERT_NOT_NULL(em);
    ASSERT_TRUE(em->isLinked());
    ASSERT_TRUE(em->isLinkedTo(m_connection));

    // Remove the link from the external mind back to m_connection
    em->linkUp(0);

    ASSERT_TRUE(!em->isLinked());

    Router * saved_em = m_character->m_externalMind;

    RootOperation op;
    op->setFrom(m_character->getId());

    m_connection->externalOperation(op, *m_connection);

    ASSERT_NOT_NULL(m_character->m_externalMind);
    ASSERT_EQUAL(m_character->m_externalMind, saved_em);
    em = dynamic_cast<ExternalMind*>(m_character->m_externalMind);
    ASSERT_NOT_NULL(em);
    ASSERT_TRUE(em->isLinked());
    ASSERT_TRUE(em->isLinkedTo(m_connection));
    ASSERT_TRUE(m_Link_send_sent.isValid());
    ASSERT_EQUAL(m_logEvent_logged, TAKE_CHAR);
}
Example #11
0
void TrustedConnectionCreatorintegration::test_external_op()
{
    // Dispatching a Talk external op from the creator should result in
    // it being passed on to the world, exactly as if this was a Character
    // except that we assume that Creator was set up linked.

    m_creator->m_externalMind = new ExternalMind(*m_creator);
    m_creator->m_externalMind->linkUp(m_connection);

    Atlas::Objects::Operation::Talk op;
    op->setFrom(m_creator->getId());

    m_connection->externalOperation(op, *m_connection);

    // BaseWorld::message should have been called from Enitty::sendWorld
    // with the Talk operation, modified to have TO set to the character.
    ASSERT_TRUE(m_BaseWorld_message_called.isValid());
    ASSERT_EQUAL(m_BaseWorld_message_called->getClassNo(),
                 Atlas::Objects::Operation::TALK_NO);
    ASSERT_TRUE(!m_BaseWorld_message_called->isDefaultTo());
    ASSERT_EQUAL(m_BaseWorld_message_called->getTo(), m_creator->getId());
    ASSERT_NOT_NULL(m_BaseWorld_message_called_from);
    ASSERT_EQUAL(m_BaseWorld_message_called_from, m_creator);
}
void EntityImporterBase::infoArrived(const Operation & op, OpVector & res)
{
    if (op->isDefaultRefno()) {
        return;
    }
    if (op->isDefaultArgs() || op->getArgs().empty()) {
        S_LOG_FAILURE("Info with no arg.");
        return;
    }
    const Root & arg = op->getArgs().front();

    if (m_state == RULE_WALKING) {
        auto& current = mRuleStack.back();
        if (arg->getId() != current.definition->getId()) {
            S_LOG_WARNING("Got info on rule " << arg->getId() << " when expecting " << current.definition->getId() << ".");
            return;
        }

        updateRule(arg, current.definition, res);

    } else if (m_state == RULE_CREATING) {
        mStats.rulesProcessedCount++;
        mStats.rulesCreateCount++;
        EventProgress.emit();
        walkRules(res);
    } else if (m_state == RULE_UPDATING) {
        mStats.rulesProcessedCount++;
        mStats.rulesUpdateCount++;
        EventProgress.emit();
        walkRules(res);
    } else if (m_state == ENTITY_CREATING) {
        if (!op.isValid()) {
            return;
        }
        mNewIds.insert(arg->getId());
        StackEntry & current = mTreeStack.back();
        current.restored_id = arg->getId();
        S_LOG_VERBOSE("Created: " << arg->getParent() << "(" << arg->getId() << ")");

        auto I = mCreateEntityMapping.find(op->getRefno());
        if (I != mCreateEntityMapping.end()) {
            //Check if there's a mind that we should send further on
            auto mindI = mPersistedMinds.find(I->second);
            if (mindI != mPersistedMinds.end()) {
                mResolvedMindMapping.emplace_back(arg->getId(), mindI->second);
            }
            mEntityIdMap.insert(std::make_pair(I->second, arg->getId()));
            mCreateEntityMapping.erase(op->getRefno());
        } else {
            S_LOG_WARNING("Got info about create for an entity which we didn't seem to have sent.");
        }

        walkEntities(res);
    } else if (m_state == ENTITY_WALKING) {
        const RootEntity& ent = smart_dynamic_cast<RootEntity>(arg);
        if (!ent.isValid()) {
            S_LOG_FAILURE("Info response is not entity.");
            return;
        }
        if (arg->isDefaultId()) {
            S_LOG_FAILURE("Corrupted info response: no id.");
        }
        const std::string & id = arg->getId();

        StackEntry & current = mTreeStack.back();
        const RootEntity& obj = current.obj;

        assert(id == obj->getId());

        if (mNewIds.find(id) != mNewIds.end() || (mTreeStack.size() != 1 && ent->isDefaultLoc()) || ent->getParent() != obj->getParent()) {
            createEntity(obj, res);
        } else {

            Root update = obj.copy();

            current.restored_id = id;

            S_LOG_VERBOSE("Updating: " << obj->getId() << " ," << obj->getParent());

            update->removeAttrFlag(Atlas::Objects::Entity::CONTAINS_FLAG);
            update->removeAttrFlag(Atlas::Objects::STAMP_FLAG);

            Set set;
            set->setArgs1(update);
            set->setFrom(mAvatarId);
            set->setTo(id);
            set->setSerialno(newSerialNumber());

            res.push_back(set);

            //Check if there's a mind, and if so put it in our map of resolved entity-to-mind mappings (since we know the entity id)
            auto mindI = mPersistedMinds.find(obj->getId());
            if (mindI != mPersistedMinds.end()) {
                mResolvedMindMapping.emplace_back(obj->getId(), mindI->second);
            }

            ++mStats.entitiesProcessedCount;
            ++mStats.entitiesUpdateCount;
            EventProgress.emit();

            m_state = ENTITY_UPDATING;
        }
    }
}