/// \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; }