From 7228d511cb221e885a9e36270419da0e1dde7d0b Mon Sep 17 00:00:00 2001 From: Eduardo Ramos Testillano Date: Tue, 25 Oct 2016 14:59:58 +0200 Subject: [PATCH] Quick solution: built-in the procedure into de own process --- example/diameter/launcher/Procedure.cpp | 287 ++++++++++++++++++++++++ example/diameter/launcher/Procedure.hpp | 26 +++ example/diameter/launcher/SConscript | 9 +- 3 files changed, 314 insertions(+), 8 deletions(-) create mode 100644 example/diameter/launcher/Procedure.cpp create mode 100644 example/diameter/launcher/Procedure.hpp diff --git a/example/diameter/launcher/Procedure.cpp b/example/diameter/launcher/Procedure.cpp new file mode 100644 index 0000000..6b0fabf --- /dev/null +++ b/example/diameter/launcher/Procedure.cpp @@ -0,0 +1,287 @@ +// ANNA - Anna is Not Nothingness Anymore // +// // +// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo // +// // +// See project site at http://redmine.teslayout.com/projects/anna-suite // +// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // + +// Standard +#include +#include +#include + +// Project +#include +#include +#include +#include +#include +#include +#include + +// Local +#include "Procedure.hpp" +#include "Launcher.hpp" + +namespace { + + void usage (std::string &response) { + response += "\n\nInvalid arguments. Provide these ones:"; + response += "\n"; + response += "\n|||[|CCR-T xml file]"; + response += "\n"; + response += "\nSequences are parsed when needed, over AVPs or internal values:"; + response += "\n"; + response += "\nSession-Id: ;;[;]"; + response += "\n \\_fixed_/\\_digits_/ \\_fixed_/\\_digits_/"; + response += "\n"; + response += "\nFor example, imagine a 13-digits diameter identity, and a 10-digits optional part."; + response += "\nThis procedure will sequence the range for 8 digits in this way:"; + response += "\n"; + response += "\n111111<7-digit-sequence>;BAT004;esmdx0900.gxrel10plusrealm.com;901<7-digit-sequence>"; + response += "\n"; + response += "\nThe same will be done in MSISDN and IMSI (Subscription-Data AVPs)."; + response += "\nFramed-IP-Address will be sequenced with a direct correspondence to hex value."; + response += "\n"; + response += "\nThen, you could provide these arguments: \"2000000|9000000|7|CCR-I.xml|CCR-T.xml\""; + response += "\n"; + } +} + +void Procedure::execute(const std::string &args, std::string &response) throw(anna::RuntimeException) { + + response = "ERROR : "; + + anna::Tokenizer targs; + targs.apply(args, "|"); + + if (targs.size() < 4) { + usage(response); + return; + } + + anna::Tokenizer::const_iterator tok_it = targs.begin(); + + std::string seq_i = anna::Tokenizer::data(tok_it); tok_it++; + std::string seq_f = anna::Tokenizer::data(tok_it); tok_it++; + std::string digits = anna::Tokenizer::data(tok_it); tok_it++; + std::string ccr_i = anna::Tokenizer::data(tok_it); tok_it++; + std::string ccr_t = ((tok_it != targs.end()) ? anna::Tokenizer::data(tok_it):""); + bool haveTermination = (ccr_t != ""); + + //response = "\n\nInitial sequence: "; response += seq_i; response += "\n"; + //response += "Final sequence: "; response += seq_f; response += "\n"; + //response += "Sequence digits: "; response += digits; response += "\n"; + //response += "CCR-Initial xml: "; response += ccr_i; response += "\n"; + //if (haveTermination) { + // response += "CCR-Termination xml: "; response += ccr_t; response += "\n"; + //} + + // Test cases cycles: + unsigned int ll_seq_i = std::atol(seq_i.c_str()); + unsigned int ll_seq_f = std::atol(seq_f.c_str()); + unsigned int ll_seq_size = ll_seq_f - ll_seq_i + 1; + int i_digits = std::atoi(digits.c_str()); + + if (ll_seq_i > ll_seq_f) { + response += " must be greater or equal than "; + return; + } + + if (seq_f.size() > i_digits) { + response += " must be lesser than number of "; + return; + } + + unsigned int ll_seq, ll_index; + anna::Millisecond timeout(5000); + + // Load xml messages: + anna::diameter::codec::Message ccri, ccrt; + anna::diameter::codec::Avp *ccri_sessionId, *ccrt_sessionId, *ccri_framedIPAddress, *ccrt_framedIPAddress, *ccri_msisdn, *ccri_imsi; + anna::diameter::codec::Avp *si1, *si2, *sidata1, *sidata2, *sitype1, *sitype2; + + try { + + ///////// CCR-Initial: + ccri.loadXML(ccr_i); + + // Session-Id & Framed-Ip-Address AVPs + ccri_sessionId = ccri.getAvp("Session-Id"); + ccri_framedIPAddress = ccri.getAvp("Framed-IP-Address"); + + // Subscription-Id AVPs + if (ccri.countAvp("Subscription-Id") != 2) { + response += "Both Subscription-Id MSISDN & IMSI Avps must be present in the CCR-Initial provided !"; + return; + } + + si1 = ccri.getAvp("Subscription-Id", 1, anna::Exception::Mode::Ignore); + si2 = ccri.getAvp("Subscription-Id", 2, anna::Exception::Mode::Ignore); + + if (!si1 || !si2) { + response += "Cannot found Subscription-Id MSISDN & IMSI Avps !" ; + return; + } + + sidata1 = si1->getAvp("Subscription-Id-Data"); + sidata2 = si2->getAvp("Subscription-Id-Data"); + sitype1 = si1->getAvp("Subscription-Id-Type"); + //sitype2 = si2->getAvp("Subscription-Id-Type"); + + if (sitype1->getEnumerated()->getValue() == anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_E164) { + ccri_msisdn = sidata1; + ccri_imsi = sidata2; + } + else { + ccri_msisdn = sidata2; + ccri_imsi = sidata1; + } + + ///////// CCR-Termination: + if (haveTermination) { + ccrt.loadXML(ccr_t); + + // Session-Id & Framed-Ip-Address AVPs + ccrt_sessionId = ccrt.getAvp("Session-Id"); + ccrt_framedIPAddress = ccrt.getAvp("Framed-IP-Address"); + } + } + catch(anna::RuntimeException &ex) { + ex.trace(); + } + + // Prepare session-id string: + std::string sessionId = ccri_sessionId->getUTF8String()->getValue(); + std::size_t last_semicolon = sessionId.rfind(";"); + anna::Tokenizer tsessionid; + tsessionid.apply(sessionId, ";"); + + if (tsessionid.size() < 4) { + response += "Session-Id must be in form ';;;'.\n\n"; + usage(response); + return; + } + + tok_it = tsessionid.begin(); + std::string d_identity = anna::Tokenizer::data(tok_it); tok_it++; tok_it++; tok_it++; + std::string o_part = anna::Tokenizer::data(tok_it); + int d_identity_len = d_identity.size(); + int left_di = d_identity_len - i_digits; + if (left_di < 0) { + response += "Session-Id diameter identity length is lower than selected number of digits "; + response += anna::functions::asString("(%d < %d).\n\n", d_identity_len, i_digits); + usage(response); + return; + } + int o_part_len = o_part.size(); + int left_op = o_part_len - i_digits; + if (left_op < 0) { + response += "Session-Id optional part length is lower than selected number of digits "; + response += anna::functions::asString("(%d < %d).\n\n", o_part_len, i_digits); + usage(response); + return; + } + + // Idem for MSISDN & IMSI Subscription-Data: + std::string msisdn = ccri_msisdn->getUTF8String()->getValue(); + int msisdn_len = msisdn.size(); + int left_msisdn = msisdn_len - i_digits; + if (left_msisdn < 0) { + response += "MSISDN Subscription-Data length is lower than selected number of digits "; + response += anna::functions::asString("(%d < %d).\n\n", left_msisdn, i_digits); + usage(response); + return; + } + std::string imsi = ccri_imsi->getUTF8String()->getValue(); + int imsi_len = imsi.size(); + int left_imsi = imsi_len - i_digits; + if (left_imsi < 0) { + response += "IMSI Subscription-Data length is lower than selected number of digits "; + response += anna::functions::asString("(%d < %d).\n\n", left_imsi, i_digits); + usage(response); + return; + } + + + // Format strings: + char ndigit_format[32]; + sprintf(ndigit_format, "%s%d%s", "%0", i_digits, "u"); + + //response += "\nSession-Id original: "; response += sessionId; + //response += "\nMSISDN original: "; response += msisdn; + //response += "\nIMSI original: "; response += imsi; + + // TestManager: + TestManager &testManager = TestManager::instantiate(); + char cad_aux[16]; + char cad_framed[16]; + TestCase *tc; + Launcher& my_app = static_cast (anna::app::functions::getApp()); + OriginHost *oh = my_app.getWorkingNode(); + + for (ll_index = 0; ll_index < ll_seq_size; ll_index++) { + + // Calculate next values //////////////////////////////////////////////////////////// + ll_seq = ll_seq_i + ll_index; + sprintf(cad_aux, ndigit_format, ll_seq); + sprintf(cad_framed, "%08x", ll_seq); + + if (ll_seq % 10000 == 0) { + std::cout << "Processing sequence " << ll_seq << std::endl; + } + + sessionId.replace(left_di, i_digits, cad_aux); + sessionId.replace(last_semicolon + left_op + 1, i_digits, cad_aux); + + msisdn.replace(left_msisdn, i_digits, cad_aux); + + imsi.replace(left_imsi, i_digits, cad_aux); + + //response += "\nSession-Id modified: "; response += sessionId; + //response += "\nMSISDN modified: "; response += msisdn; + //response += "\nIMSI modified: "; response += imsi; + //response += "\nFramedIP modified: "; response += cad_framed; + + // Update diameter messages ///////////////////////////////////////////////////////// + ccri_sessionId->getUTF8String()->setValue(sessionId); + ccri_framedIPAddress->getOctetString()->fromHexString(cad_framed); + ccri_msisdn->getUTF8String()->setValue(msisdn); + ccri_imsi->getUTF8String()->setValue(imsi); + + if (haveTermination) { + ccrt_sessionId->getUTF8String()->setValue(sessionId); + ccrt_framedIPAddress->getOctetString()->fromHexString(cad_framed); + } + + // Create testcase: + tc = testManager.getTestCase(ll_index+1); + // test|__TESTID__|timeout|6000 + // test|__TESTID__|sendxml2e|ccr-i.xml + // test|__TESTID__|waitfe|272|0|||11111__SEQ8__;BAT004;esmdx0900.gxrel10plusrealm.com;90__SEQ8__|2001 + // test|__TESTID__|sendxml2e|ccr-t.xml + // test|__TESTID__|waitfe|272|0|||11111__SEQ8__;BAT004;esmdx0900.gxrel10plusrealm.com;90__SEQ8__|2001 + + // Step 1: timeout 5000 ms: + tc->addTimeout(timeout); + + // Step 2: sendxml2e: CCR-Initial + tc->addSendxml2e(ccri.code(), oh, -1 /* 'wait for request' step number for answers */); + + // Step 3: waitfe: CCA with same session id + // PARAM: 1 2 3 4 5 6 7 8 9 10 11 + // wait|[code]|[bitR]|[hopByHop]|[applicationId]|[sessionId]|[resultCode]|[msisdn]|[imsi]|[serviceContextId] + tc->addWait(true /* from entity */, "272", "0", "", "", sessionId, "2001", "", "", ""); + + if (haveTermination) { + // Step 4: sendxml2e: CCR-Termination + tc->addSendxml2e(ccrt.code(), oh, -1 /* 'wait for request' step number for answers */); + + // Step 5: waitfe: CCA with same session id + tc->addWait(true /* from entity */, "272", "0", "", "", sessionId, "2001", "", "", ""); + } + } // loop + + response = "Programming complete !"; +} + diff --git a/example/diameter/launcher/Procedure.hpp b/example/diameter/launcher/Procedure.hpp new file mode 100644 index 0000000..6720136 --- /dev/null +++ b/example/diameter/launcher/Procedure.hpp @@ -0,0 +1,26 @@ +// ANNA - Anna is Not Nothingness Anymore // +// // +// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo // +// // +// See project site at http://redmine.teslayout.com/projects/anna-suite // +// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // + + +#ifndef dynamic_launcher_gx_00001_hpp +#define dynamic_launcher_gx_00001_hpp + +// Project +#include + + + +class Procedure { + anna::comm::Application *a_app; + + public: + Procedure(anna::comm::Application *app) : a_app(app) {;} + + virtual void execute(const std::string &args, std::string &response) throw(anna::RuntimeException); +}; + +#endif diff --git a/example/diameter/launcher/SConscript b/example/diameter/launcher/SConscript index d9d48ce..06746a6 100644 --- a/example/diameter/launcher/SConscript +++ b/example/diameter/launcher/SConscript @@ -19,12 +19,6 @@ for module in modules: kk = pwd.replace (pPath, ("source/" + module + "/")) anna_libpaths.append (pwd.replace (pPath, ("source/" + module + "/"))) -# dynamic lib: -anna_libs.append ("anna_dynamicLauncherProcedure") -variant = env ['VARIANT'] -dynamic_libpath = os.path.join (pwd, "../../../../dynamic/launcher/default/" + variant) -anna_libpaths.append (dynamic_libpath) - anna_rlibs = list(anna_libs) anna_rlibs.reverse() @@ -46,8 +40,7 @@ localEnv.Append(LIBPATH = anna_libpaths) # Process includes (avoid mandatory using of quoted includes and ../ paths from testing directory): current_directory = Dir ('.').abspath testing_include = os.path.join (current_directory, "testing") -dynamic_include = os.path.join (pwd, "../../../../dynamic/launcher/default/") -localEnv.Append (CPPPATH = [current_directory, testing_include, dynamic_include]) +localEnv.Append (CPPPATH = [current_directory, testing_include]) result = localEnv.Program (pName, Glob ('*.cpp') + Glob ('testing/*.cpp')) -- 2.20.1