コード例 #1
0
ファイル: Peer.cpp プロジェクト: erikogenvik/cyphesis
/// \brief Teleport an entity to the connected peer
///
/// @param ent The entity to be teleported
/// @return Returns 0 on success and -1 on failure
int Peer::teleportEntity(const Entity * ent)
{
    if (m_state != PEER_AUTHENTICATED) {
        log(ERROR, "Peer not authenticated yet.");
        return -1;
    }

    long iid = ent->getIntId();
    if (m_teleports.find(iid) != m_teleports.end()) {
        log(INFO, "Transfer of this entity already in progress");
        return -1;
    }

    struct timeval timeVal;
    gettimeofday(&timeVal, NULL);
    time_t teleport_time = timeVal.tv_sec;

    // Add a teleport state object to identify this teleport request
    TeleportState * s = new TeleportState(teleport_time);
    if (s == NULL) {
        log(ERROR, "Unable to allocate teleport state object");
        return -1;
    }

    // Check if the entity has a mind
    const Character * chr = dynamic_cast<const Character *>(ent);
    ExternalMind * mind = 0;
    if (chr != 0 && chr->m_externalMind != 0) {
        mind = dynamic_cast<ExternalMind*>(chr->m_externalMind);
    }

    Atlas::Objects::Entity::Anonymous atlas_repr;
    ent->addToEntity(atlas_repr);

    Create op;
    op->setFrom(m_accountId);
    op->setSerialno(iid);
    op->setArgs1(atlas_repr);
    
    if (mind != 0 && mind->isConnected()) {
        // Entities with a mind require an additional one-time possess key that
        // is used by the client to authenticate a teleport on the destination
        // peer
        std::string key;
        log(INFO, "Entity has a mind. Generating random key");
        // FIXME non-random, plus potetial timing attack.
        WFMath::MTRand generator;
        for(int i=0;i<32;i++) {
            char ch = (char)((int)'a' + generator.rand(25));
            key += ch;
        }

        s->setKey(key);
        // Add an additional possess key argument
        log(INFO, String::compose("Adding possess key %1 to Create op", key));
        Anonymous key_arg;
        key_arg->setAttr("possess_key", key);

        std::vector<Root> & create_args = op->modifyArgs();
        create_args.push_back(key_arg);
    }
    m_commClient.send(op);
    log(INFO, "Sent Create op to peer");
    
    // Set it as validated and add to the list of teleports
    s->setRequested();
    m_teleports[iid] = s;
    log(INFO, "Added new teleport state");

    return 0;
}