X-Git-Url: https://git.teslayout.com/public/public/public/?a=blobdiff_plain;f=source%2Fdiameter.comm%2FServerSession.cpp;h=ab7ca11102d1c2b643fca2b27a8768494fcdcbb2;hb=HEAD;hp=1e2728cb4c25132b48d5c224a8c6664cef6dba2f;hpb=4c3f0a4d7e4db76996404d80c6f939548fca656f;p=anna.git diff --git a/source/diameter.comm/ServerSession.cpp b/source/diameter.comm/ServerSession.cpp index 1e2728c..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,12 +55,10 @@ 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) // realmente no es necesario, los Message son por defecto de aplicacion + a_receiverFactory(this) { initialize(); } -void ServerSession::initialize() throw() { +void ServerSession::initialize() { Session::initialize(); a_parent = NULL; a_clientSocket = NULL; @@ -67,22 +67,21 @@ void ServerSession::initialize() throw() { //ServerSession::~ServerSession() {;} -void ServerSession::setClientSocket(anna::comm::ClientSocket *clientSocket) throw() { +void ServerSession::setClientSocket(anna::comm::ClientSocket *clientSocket) { a_clientSocket = clientSocket; a_clientSocket->setReceiverFactory(a_receiverFactory); } -const std::string& ServerSession::getAddress() const throw() { +const std::string& ServerSession::getAddress() const { return a_parent->getKey().first; } -int ServerSession::getPort() const throw() { +int ServerSession::getPort() const { return a_parent->getKey().second; } - -const Response* ServerSession::send(const Message* message) throw(anna::RuntimeException) { +const Response* ServerSession::send(const Message* message) noexcept(false) { LOGMETHOD(anna::TraceMethod traceMethod(a_className, "send", ANNA_FILE_LOCATION)); if(!message) @@ -212,22 +211,6 @@ const Response* ServerSession::send(const Message* message) throw(anna::RuntimeE 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 @@ -261,7 +244,7 @@ const Response* ServerSession::send(const Message* message) throw(anna::RuntimeE -bool ServerSession::unbind(bool forceDisconnect) throw(anna::RuntimeException) { +bool ServerSession::unbind(bool forceDisconnect) noexcept(false) { LOGMETHOD(anna::TraceMethod traceMethod(a_className, "unbind", ANNA_FILE_LOCATION)); if(a_state == State::Closed) @@ -308,12 +291,12 @@ bool ServerSession::unbind(bool forceDisconnect) throw(anna::RuntimeException) { return false; } -void ServerSession::eventPeerShutdown() throw() { +void ServerSession::eventPeerShutdown() { // Inform father server: a_parent->eventPeerShutdown(this); } -void ServerSession::eventRequestRetransmission(Message *request) throw() { +void ServerSession::eventRequestRetransmission(Message *request) { // OAM OamModule &oamModule = OamModule::instantiate(); @@ -324,32 +307,64 @@ void ServerSession::eventRequestRetransmission(Message *request) throw() { a_parent->eventRequestRetransmission(this, request); } -void ServerSession::eventResponse(const Response& response) throw(anna::RuntimeException) { +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) throw(anna::RuntimeException) { +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) throw(anna::RuntimeException) { +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) throw(anna::RuntimeException) { +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; } //------------------------------------------------------------------------------------------ // Se invoca desde el diameter::comm::Receiver //------------------------------------------------------------------------------------------ void ServerSession::receive(const anna::comm::Message& message) -throw(anna::RuntimeException) { +noexcept(false) { LOGMETHOD(anna::TraceMethod traceMethod(a_className, "receive", ANNA_FILE_LOCATION)); + + // Activity: updateIncomingActivityTime(); activateTimer(); @@ -361,25 +376,23 @@ throw(anna::RuntimeException) { 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(); oamModule.count(isRequest ? OamModule::Counter::RequestReceived : OamModule::Counter::AnswerReceived); oamModule.count(isRequest ? OamModule::Counter::RequestReceivedOnServerSession : OamModule::Counter::AnswerReceivedOnServerSession); // Statistic (size) - a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize()); // only on reception (application could manage sent sizes) + 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, @@ -391,14 +404,35 @@ throw(anna::RuntimeException) { // 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); - sendCEA(); + // Basic DRA: + originHost->getCommEngine()->manageDrDhServerSession(this, true /* register */); + + sendCEA(originHost->getCommEngine(), db); //activateTimer(); // Ya se invoca al inicio de este metodo ::receive //bool changes = a_parent->refreshAvailability(); return; // (*) @@ -406,29 +440,34 @@ throw(anna::RuntimeException) { // 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 } } try { // application message counters - ApplicationMessageOamModule::instantiate().count(cid.first, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Request_Received_AsServer); + ApplicationMessageOamModule::instantiate().count(cid.first, -1 /* no result code */, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Request_Received_AsServer); + + if (!originHost) return; // TODO, responding DWA with result code error - eventRequest(db); + eventRequest(db, originHost); } catch(anna::RuntimeException& ex) { ex.trace(); } @@ -462,7 +501,8 @@ throw(anna::RuntimeException) { } } - 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); @@ -479,9 +519,10 @@ throw(anna::RuntimeException) { oamModule.activateAlarm(OamModule::Alarm::AnswerReceivedOnServerSessionUnknown); // application message counters - ApplicationMessageOamModule::instantiate().count(cid.first, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_UnknownReceived_AsServer); + 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); @@ -501,14 +542,14 @@ throw(anna::RuntimeException) { anna::Millisecond current = (anna::Millisecond)anna::functions::millisecond(); anna::Millisecond request = response->getRequest()->getRequestTimestampMs(); anna::Millisecond timeToAnswerMs = current - request; - a_parent->updateProcessingTimeStatisticConcept(timeToAnswerMs); - LOGDEBUG - ( - std::string msg = "This diameter request context lasted "; - msg += anna::functions::asString(timeToAnswerMs); - msg += " milliseconds at diameter client (included network time)"; - anna::Logger::debug(msg, ANNA_FILE_LOCATION); - ); + a_parent->updateProcessingTimeStatisticConcept(timeToAnswerMs, cid); + //LOGDEBUG + //( + // std::string msg = "This diameter request context lasted "; + // msg += anna::functions::asString(timeToAnswerMs); + // msg += " milliseconds at diameter client (included network time)"; + // anna::Logger::debug(msg, ANNA_FILE_LOCATION); + //); // Progress origin for tracking purposes on asyncronous boxes with both diameter interfaces (entities and clients) Message * requestMessage = const_cast(response->getRequest()); requestMessage->setRequestClientSessionKey(response->getRequest()->getRequestClientSessionKey()); // "" means unkown/unset @@ -530,9 +571,10 @@ throw(anna::RuntimeException) { diameter::codec::functions::setEndToEnd((anna::DataBlock&)db, response->getRequest()->getRequestEndToEnd()); // application message counters - ApplicationMessageOamModule::instantiate().count(cid.first, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_Received_AsServer); + 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(); @@ -546,7 +588,7 @@ throw(anna::RuntimeException) { unbind(true /* always immediate */); } -void ServerSession::finalize() throw() { +void ServerSession::finalize() { LOGMETHOD(anna::TraceMethod traceMethod(a_className, "finalize", ANNA_FILE_LOCATION)); // Configuration overiddings setOnDisconnect(OnDisconnect::IgnorePendings); @@ -565,7 +607,7 @@ void ServerSession::finalize() throw() { } // Inform father local server (availability changes): - bool changes = getParent()->refreshAvailability(); + getParent()->refreshAvailability(); // OAM bool multipleConnections = (getParent()->getMaxConnections() > 1); std::string socket = anna::functions::socketLiteralAsString(getAddress(), getPort()); @@ -582,11 +624,12 @@ void ServerSession::finalize() throw() { -void ServerSession::sendCEA() -throw(anna::RuntimeException) { +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 @@ -633,11 +676,11 @@ throw(anna::RuntimeException) { } } -void ServerSession::sendDWA() -throw(anna::RuntimeException) { +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); @@ -652,7 +695,7 @@ throw(anna::RuntimeException) { // Se invoca desde diameter::comm::Timer //------------------------------------------------------------------------- void ServerSession::expireResponse(diameter::comm::Response* response) -throw() { +{ LOGMETHOD(anna::TraceMethod traceMethod(a_className, "expireResponse", ANNA_FILE_LOCATION)); Session::expireResponse(response); // OAM @@ -665,7 +708,7 @@ throw() { } std::string ServerSession::asString() const -throw() { +{ string result = Session::asString(); result += " | Parent Local Server: "; result += anna::functions::socketLiteralAsString(getAddress(), getPort()); @@ -680,7 +723,7 @@ throw() { } anna::xml::Node* ServerSession::asXML(anna::xml::Node* parent) const -throw() { +{ anna::xml::Node* result = Session::asXML(parent); parent->createChild("diameter.comm.ServerSession"); result->createAttribute("ParentLocalServer", anna::functions::socketLiteralAsString(getAddress(), getPort())); @@ -695,7 +738,7 @@ throw() { //------------------------------------------------------------------------------ //------------------------------------------------------ ServerSession::expire() //------------------------------------------------------------------------------ -void ServerSession::expire(anna::timex::Engine *timeController) throw(anna::RuntimeException) { +void ServerSession::expire(anna::timex::Engine *timeController) noexcept(false) { LOGMETHOD(anna::TraceMethod traceMethod(a_className, "expire (inactivity check timer)", ANNA_FILE_LOCATION)); LOGWARNING(anna::Logger::warning("Detecting anomaly (too inactivity time) over server session. Resetting", ANNA_FILE_LOCATION)); // OAM @@ -714,14 +757,14 @@ void ServerSession::expire(anna::timex::Engine *timeController) throw(anna::Runt unbind(true /* always immediate */); // no delegamos en un planning o similar } -void ServerSession::setAllowedInactivityTime(const anna::Millisecond & allowedInactivityTime) throw() { +void ServerSession::setAllowedInactivityTime(const anna::Millisecond & allowedInactivityTime) { setTimeout(allowedInactivityTime); } //------------------------------------------------------------------------------ //---------------------------------- ServerSession::updateIncomingActivityTime() //------------------------------------------------------------------------------ -void ServerSession::updateIncomingActivityTime() throw() { +void ServerSession::updateIncomingActivityTime() { Session::updateIncomingActivityTime(); a_parent->updateIncomingActivityTime(); } @@ -730,7 +773,7 @@ void ServerSession::updateIncomingActivityTime() throw() { //------------------------------------------------------------------------------ //---------------------------------- ServerSession::updateOutgoingActivityTime() //------------------------------------------------------------------------------ -void ServerSession::updateOutgoingActivityTime(void) throw() { +void ServerSession::updateOutgoingActivityTime(void) { Session::updateOutgoingActivityTime(); a_parent->updateOutgoingActivityTime(); } @@ -739,7 +782,7 @@ void ServerSession::updateOutgoingActivityTime(void) throw() { //------------------------------------------------------------------------------ //----------------------------------------------- ServerSession::countSendings() //------------------------------------------------------------------------------ -void ServerSession::countSendings(const diameter::CommandId & cid, unsigned int aid, bool ok)throw() { +void ServerSession::countSendings(const diameter::CommandId & cid, unsigned int aid, bool ok){ OamModule &oamModule = OamModule::instantiate(); ApplicationMessageOamModule &appMsgOamModule = ApplicationMessageOamModule::instantiate(); @@ -757,7 +800,7 @@ void ServerSession::countSendings(const diameter::CommandId & cid, unsigned int else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Request) oamModule.count(OamModule::Counter::DPRSentOK); // Application messages: else { - appMsgOamModule.count(cid.first, aid, isRequest ? ApplicationMessageOamModule::Counter::Request_SentOK_AsServer : ApplicationMessageOamModule::Counter::Answer_SentOK_AsServer); + appMsgOamModule.count(cid.first, -1 /* no result code */, aid, isRequest ? ApplicationMessageOamModule::Counter::Request_SentOK_AsServer : ApplicationMessageOamModule::Counter::Answer_SentOK_AsServer); } } else { // Main counters: @@ -771,7 +814,7 @@ void ServerSession::countSendings(const diameter::CommandId & cid, unsigned int else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Request) oamModule.count(OamModule::Counter::DPRSentNOK); // Application messages: else { - appMsgOamModule.count(cid.first, aid, isRequest ? ApplicationMessageOamModule::Counter::Request_SentNOK_AsServer : ApplicationMessageOamModule::Counter::Answer_SentNOK_AsServer); + appMsgOamModule.count(cid.first, -1 /* no result code */, aid, isRequest ? ApplicationMessageOamModule::Counter::Request_SentNOK_AsServer : ApplicationMessageOamModule::Counter::Answer_SentNOK_AsServer); } } }