Quick solution: built-in the procedure into de own process
authorEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Tue, 25 Oct 2016 12:59:58 +0000 (14:59 +0200)
committerEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Tue, 25 Oct 2016 12:59:58 +0000 (14:59 +0200)
example/diameter/launcher/Procedure.cpp [new file with mode: 0644]
example/diameter/launcher/Procedure.hpp [new file with mode: 0644]
example/diameter/launcher/SConscript

diff --git a/example/diameter/launcher/Procedure.cpp b/example/diameter/launcher/Procedure.cpp
new file mode 100644 (file)
index 0000000..6b0fabf
--- /dev/null
@@ -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 <iostream>
+#include <string>
+#include <cstdlib>
+
+// Project
+#include <anna/core/util/Tokenizer.hpp>
+#include <anna/core/Exception.hpp>
+#include <TestManager.hpp>
+#include <anna/diameter/codec/Message.hpp>
+#include <anna/diameter/codec/Avp.hpp>
+#include <anna/diameter/helpers/dcca/functions.hpp>
+#include <anna/diameter/helpers/dcca/functions.hpp>
+
+// Local
+#include "Procedure.hpp"
+#include "Launcher.hpp"
+
+namespace {
+
+   void usage (std::string &response) {
+     response += "\n\nInvalid arguments. Provide these ones:";
+     response += "\n";
+     response += "\n<initial sequence>|<final sequence>|<digits>|<CCR-I xml file>[|CCR-T xml file]";
+     response += "\n";
+     response += "\nSequences are parsed when needed, over AVPs or internal values:";
+     response += "\n";
+     response += "\nSession-Id: <DiameterIdentity>;<high 32 bits>;<low 32 bits>[;<optional value>]";
+     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 += "<final sequence> must be greater or equal than <initial sequence>";
+    return;
+  }
+
+  if (seq_f.size() > i_digits) {
+    response += "<final sequence> must be lesser than number of <digits>";
+    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 '<a>;<b>;<c>;<d>'.\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 <Launcher&>(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<fe/fc>|[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 (file)
index 0000000..6720136
--- /dev/null
@@ -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 <anna/comm/comm.hpp>
+
+
+
+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
index d9d48ce..06746a6 100644 (file)
@@ -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'))