void ClientConnection::sendError(const std::string& msg, const RootOperation& op) { Error errOp; errOp->setRefno(op->getSerialno()); errOp->setTo(op->getFrom()); Root arg0; arg0->setAttr("message", msg); std::vector<Root>& args = errOp->modifyArgs(); args.push_back(arg0); args.push_back(op); send(errOp); }
void ClientConnection::dispatch(const RootOperation& op) { const std::vector<Root>& args = op->getArgs(); if (op->getFrom().empty()) { if (m_account.empty()) { // not logged in yet if (op->getClassNo() == LOGIN_NO) { processLogin(smart_dynamic_cast<Login>(op)); return; } if (op->getClassNo() == CREATE_NO) { assert(!args.empty()); processAccountCreate(smart_dynamic_cast<Create>(op)); return; } } if (op->getClassNo() == GET_NO) { processAnonymousGet(smart_dynamic_cast<Get>(op)); return; } if (op->getClassNo() == LOGOUT_NO) { return; } throw TestFailure("got anonymous op I couldn't dispatch"); } if (op->getFrom() == m_account) { dispatchOOG(op); return; } if (m_agents.count(op->getFrom())) { m_agents[op->getFrom()]->processOp(op); return; } if (entityIsCharacter(op->getFrom())) { // IG activation activateCharacter(op->getFrom(), op); return; } debug() << "totally failed to handle operation " << objectSummary(op); }
void Connection::dispatchOp(const RootOperation& op) { try { Router::RouterResult rr = Router::IGNORED; bool anonymous = op->isDefaultTo(); if (m_responder->handleOp(op)) return; // locate a router based on from if (!op->isDefaultFrom()) { IdRouterMap::const_iterator R = m_fromRouters.find(op->getFrom()); if (R != m_fromRouters.end()) { rr = R->second->handleOperation(op); if ((rr == Router::HANDLED) || (rr == Router::WILL_REDISPATCH)) return; } } // locate a router based on the op's TO value if (!anonymous) { IdRouterMap::const_iterator R = m_toRouters.find(op->getTo()); if (R != m_toRouters.end()) { rr = R->second->handleOperation(op); if ((rr == Router::HANDLED) || (rr == Router::WILL_REDISPATCH)) return; } else if (!m_toRouters.empty()) { warning() << "recived op with TO=" << op->getTo() << ", but no router is registered for that id"; } } // special-case, server info refreshes are handled here directly if (op->instanceOf(INFO_NO) && anonymous) { handleServerInfo(op); return; } // go to the default router if (m_defaultRouter) rr = m_defaultRouter->handleOperation(op); if (rr != Router::HANDLED) warning() << "no-one handled op:" << op; } catch (Atlas::Exception& ae) { error() << "caught Atlas exception: " << ae.getDescription() << " while dispatching op:\n" << op; } }
Router::RouterResult EntityRouter::handleOperation(const RootOperation& op) { assert(op->getFrom() == m_entity->getId()); const std::vector<Root>& args = op->getArgs(); // note it's important we match exactly on sight here, and not deried ops // like appearance and disappearance if (op->getClassNo() == SIGHT_NO) { assert(!args.empty()); RootOperation sop = smart_dynamic_cast<RootOperation>(args.front()); if (sop.isValid()) return handleSightOp(sop); } if (op->getClassNo() == SOUND_NO) { assert(!args.empty()); if (args.front()->getClassNo() == TALK_NO) { RootOperation talk = smart_dynamic_cast<RootOperation>(args.front()); m_entity->onTalk(talk); return HANDLED; } TypeInfo* ty = typeService()->getTypeForAtlas(args.front()); if (!ty->isBound()) { new TypeBoundRedispatch(m_entity->getView()->getAvatar()->getConnection(), op, ty); return WILL_REDISPATCH; } if (ty->isA(typeService()->getTypeByName("action"))) { // sound of action RootOperation act = smart_dynamic_cast<RootOperation>(args.front()); m_entity->onSoundAction(act); return HANDLED; } warning() << "entity " << m_entity->getId() << " emitted sound with strange argument: " << op; // other sounds ! } return IGNORED; }