X-Git-Url: https://git.teslayout.com/public/public/public/?p=anna.git;a=blobdiff_plain;f=source%2Fdiameter.comm%2FServerSession.cpp;h=ab7ca11102d1c2b643fca2b27a8768494fcdcbb2;hp=b88da8d89d2b0554628e9640c5d05960b79b062f;hb=HEAD;hpb=7681cb4079366eb6908dd5d0dc0124c3fcef4b6b diff --git a/source/diameter.comm/ServerSession.cpp b/source/diameter.comm/ServerSession.cpp index b88da8d..ab7ca11 100644 --- a/source/diameter.comm/ServerSession.cpp +++ b/source/diameter.comm/ServerSession.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include @@ -53,9 +55,7 @@ const anna::Millisecond ServerSession::DefaultAllowedInactivityTime(90000); // I ServerSession::ServerSession() : Session("diameter::comm::ServerSession", "Diameter Inactivity Detection Timer"), - a_receiverFactory(this), - a_cer(ClassCode::Bind), - a_dwr(ClassCode::ApplicationMessage) // not actually needed; Message is application type by default + a_receiverFactory(this) { initialize(); } void ServerSession::initialize() { @@ -211,22 +211,6 @@ const Response* ServerSession::send(const Message* message) noexcept(false) { updateOutgoingActivityTime(); // OAM countSendings(cid, aid, true /* send ok */); - // Trace non-application messages: - LOGDEBUG( - - if( (cid == helpers::base::COMMANDID__Device_Watchdog_Request) || - (cid == helpers::base::COMMANDID__Disconnect_Peer_Request)) { - anna::Logger::debug("Sent DataBlock to XML representation:", ANNA_FILE_LOCATION); - try { - anna::diameter::codec::Message msg(a_engine->getBaseProtocolCodecEngine()); msg.decode(message->getBody()); /* decode to be traced */ - } - catch(anna::RuntimeException &ex) { - std::string msg = ex.getText(); - msg += " | Use diameter::comm::Engine::setBaseProtocolCodecEngine() to allow internal base protocol messages full tracing"; - anna::Logger::debug(msg, ANNA_FILE_LOCATION); - } - } - ); // Restore sequences: if(fixed) message_nc->restoreSequencesAfterFix(); // restore to application sequences after fix @@ -323,24 +307,54 @@ void ServerSession::eventRequestRetransmission(Message *request) { a_parent->eventRequestRetransmission(this, request); } -void ServerSession::eventResponse(const Response& response) noexcept(false) { +void ServerSession::eventResponse(const Response& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) { // Inform father server: - a_parent->eventResponse(response); + a_parent->eventResponse(response, myNode); } -void ServerSession::eventRequest(const anna::DataBlock &request) noexcept(false) { +void ServerSession::eventRequest(const anna::DataBlock &request, const anna::diameter::comm::OriginHost *myNode) noexcept(false) { // Inform father server: - a_parent->eventRequest(this, request); + a_parent->eventRequest(this, request, myNode); } -void ServerSession::eventUnknownResponse(const anna::DataBlock& response) noexcept(false) { +void ServerSession::eventUnknownResponse(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) { // Inform father server: - a_parent->eventUnknownResponse(this, response); + a_parent->eventUnknownResponse(this, response, myNode); } -void ServerSession::eventDPA(const anna::DataBlock& response) noexcept(false) { +void ServerSession::eventDPA(const anna::DataBlock& response, const anna::diameter::comm::OriginHost *myNode) noexcept(false) { // Inform father server: - a_parent->eventDPA(this, response); + a_parent->eventDPA(this, response, myNode); +} + + +anna::U32 ServerSession::getAuthApplicationIdFromCER(const anna::DataBlock &cer, bool &found) const { + + anna::U32 result{}; + found = true; + + anna::diameter::codec::Message codecMsg; // codec engine to pre-assigned, but will be inferred from ApplicationId during decoding: + try { codecMsg.decode(cer); } catch(anna::RuntimeException &ex) { ex.trace(); found = false; return result; } + + // Look at first level: + try { + result = codecMsg.getAvp(helpers::base::AVPID__Auth_Application_Id)->getUnsigned32()->getValue(); + } + catch(anna::RuntimeException &ex) { + found = false; + } + + // Look within Vendor-Specific-Application-Id: + if (!found) { + try { + result = codecMsg.getAvp(helpers::base::AVPID__Vendor_Specific_Application_Id)->getAvp(helpers::base::AVPID__Auth_Application_Id)->getUnsigned32()->getValue(); + } + catch(anna::RuntimeException &ex) { + found = false; + } + } + + return result; } //------------------------------------------------------------------------------------------ @@ -349,6 +363,8 @@ void ServerSession::eventDPA(const anna::DataBlock& response) noexcept(false) { void ServerSession::receive(const anna::comm::Message& message) noexcept(false) { LOGMETHOD(anna::TraceMethod traceMethod(a_className, "receive", ANNA_FILE_LOCATION)); + + // Activity: updateIncomingActivityTime(); activateTimer(); @@ -360,18 +376,6 @@ noexcept(false) { std::string msg = "Received diameter message: "; msg += anna::diameter::functions::commandIdAsPairString(cid); anna::Logger::debug(msg, ANNA_FILE_LOCATION); - - if( (cid == helpers::base::COMMANDID__Capabilities_Exchange_Request) || - (cid.first == helpers::base::COMMANDID__Device_Watchdog_Request.first)) { - try { - anna::diameter::codec::Message dmsg(a_engine->getBaseProtocolCodecEngine()); dmsg.decode(db); /* decode to be traced */ - } - catch(anna::RuntimeException &ex) { - std::string msg = ex.getText(); - msg += " | Use diameter::comm::Engine::setBaseProtocolCodecEngine() to allow internal base protocol messages full tracing"; - anna::Logger::debug(msg, ANNA_FILE_LOCATION); - } - } ); // Main counters: OamModule &oamModule = OamModule::instantiate(); @@ -380,6 +384,16 @@ noexcept(false) { // Statistic (size) a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize(), cid); // only on reception (application could manage sent sizes) + // OriginHostManager (to register remote origin host in order to associate with specific comm engine): + anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate(); + + // Extract OriginHost from datablock (db): + std::string remoteOriginHost = anna::diameter::helpers::base::functions::getOriginHost(db); + LOGDEBUG(anna::Logger::debug(anna::functions::asString("REMOTE ORIGIN HOST FOR THE MESSAGE RECEIVED: %s", remoteOriginHost.c_str()), ANNA_FILE_LOCATION)); + + // Now, get the corresponding own origin host for it; in case of CER received, this will be unkonwn: + const anna::diameter::comm::OriginHost *originHost = ohm.getOriginHostForRemoteOriginHost(remoteOriginHost); + if(isRequest) { // Si recibo un request, el message solo tiene fiable el DataBlock. Como por defecto se construye como ApplicationMessage, // el unico caso que no cuadraria seria la recepcion de un CER. Lo que hacemos es NO PROGRESAR NUNCA un CER (*). @@ -390,17 +404,35 @@ noexcept(false) { // Received CER if(cid == helpers::base::COMMANDID__Capabilities_Exchange_Request) { + + // For CERs, we need to extract the Auth-Application-Id: + bool found; + anna::U32 authApplicationId = getAuthApplicationIdFromCER(db, found); + + // Now, sequential search in OriginHostManager for that id: + anna::diameter::comm::OriginHost *originHost = ohm.getOriginHost(authApplicationId); + + if (!originHost) { + LOGWARNING(anna::Logger::warning("DIAMETER_NO_COMMON_APPLICATION with received CER. TODO: send CEA with that result code", ANNA_FILE_LOCATION)); + unbind(true /* always immediate */); + return; + } + + // Map origin host of received CER, to own OriginHost pointer. This will be used in future: DWR, DPR, normal messages + ohm.registerRemoteOriginHost(remoteOriginHost, originHost->getName()); + + + // OAM oamModule.count(OamModule::Counter::CERReceived); if(a_state == State::Bound) { LOGWARNING(anna::Logger::warning("Received another CER over already bound connection. Anyway, will be replied with CEA", ANNA_FILE_LOCATION)); } - a_cer.setBody(db); // Basic DRA: - getParent()->getEngine()->manageDrDhServerSession(this, true /* register */); + originHost->getCommEngine()->manageDrDhServerSession(this, true /* register */); - sendCEA(); + sendCEA(originHost->getCommEngine(), db); //activateTimer(); // Ya se invoca al inicio de este metodo ::receive //bool changes = a_parent->refreshAvailability(); return; // (*) @@ -408,20 +440,23 @@ noexcept(false) { // Received DWR else if(cid == helpers::base::COMMANDID__Device_Watchdog_Request) { oamModule.count(OamModule::Counter::DWRReceived); - a_dwr.setBody(db); - sendDWA(); + + if (!originHost) return; // TODO, responding DWA with result code error + + sendDWA(originHost->getCommEngine(), db); return; // (**) } // Received DPR else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Request) { oamModule.count(OamModule::Counter::DPRReceived); + if (!originHost) return; // TODO, responding DPA with result code error + if(a_state == State::Bound) { - a_dpr.setBody(db); setState(State::Disconnecting); LOGWARNING(anna::Logger::warning("DPR has been received from peer (diameter client)", ANNA_FILE_LOCATION)); // Ignore pending on server sessions: - /*if (getOTARequests() == 0) */sendDPA(); + /*if (getOTARequests() == 0) */sendDPA(originHost->getCommEngine(), db); return; // DPR won't be informed because virtual readDPA is available for this } } @@ -430,7 +465,9 @@ noexcept(false) { // application message counters ApplicationMessageOamModule::instantiate().count(cid.first, -1 /* no result code */, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Request_Received_AsServer); - eventRequest(db); + if (!originHost) return; // TODO, responding DWA with result code error + + eventRequest(db, originHost); } catch(anna::RuntimeException& ex) { ex.trace(); } @@ -464,7 +501,8 @@ noexcept(false) { } } - eventDPA(db); + if (originHost) + eventDPA(db, originHost); } else if(cid == helpers::base::COMMANDID__Device_Watchdog_Answer) { // non usual (server should not send DWR's) oamModule.count(OamModule::Counter::DWAReceived); @@ -483,7 +521,8 @@ noexcept(false) { // application message counters ApplicationMessageOamModule::instantiate().count(cid.first, resultCode, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_UnknownReceived_AsServer); - eventUnknownResponse(db); + if (originHost) + eventUnknownResponse(db, originHost); string msg(asString()); msg += anna::functions::asString(" | Response received from client, for non registered context (HopByHop: %u)", hopByHop); @@ -534,7 +573,8 @@ noexcept(false) { // application message counters ApplicationMessageOamModule::instantiate().count(cid.first, resultCode, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_Received_AsServer); - eventResponse(*response); + if (originHost) + eventResponse(*response, originHost); } catch(anna::RuntimeException& ex) { ex.trace(); @@ -584,11 +624,12 @@ void ServerSession::finalize() { -void ServerSession::sendCEA() +void ServerSession::sendCEA(const Engine *commEngine, const anna::DataBlock &cerDataBlock) noexcept(false) { LOGMETHOD(anna::TraceMethod traceMethod(a_className, "sendCEA", ANNA_FILE_LOCATION)); + anna::DataBlock cea(true); - a_engine->readCEA(cea, a_cer.getBody()); // Asume that CEA is valid ... + commEngine->readCEA(cea, cerDataBlock); // Asume that CEA is valid ... // If one peer sends a CER message to another Peer and receiver does not have support for // // 1) any common application then it must return the CEA with Result-Code Avp set to DIAMETER_NO_COMMON_APPLICATION @@ -635,11 +676,11 @@ noexcept(false) { } } -void ServerSession::sendDWA() +void ServerSession::sendDWA(const Engine *commEngine, const anna::DataBlock &dwrDataBlock) noexcept(false) { LOGMETHOD(anna::TraceMethod traceMethod(a_className, "sendDWA", ANNA_FILE_LOCATION)); anna::DataBlock dwa(true); - a_engine->readDWA(dwa, a_dwr.getBody()); // Asume that DWA is valid ... + commEngine->readDWA(dwa, dwrDataBlock); // Asume that DWA is valid ... if(dwa.isEmpty()) throw anna::RuntimeException("This diameter agent defines an empty DWA message. Remote client never will validate this connection health", ANNA_FILE_LOCATION);