-// ANNA - Anna is Not 'N' Anymore
+// ANNA - Anna is Not Nothingness Anymore
//
// (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
//
-// https://bitbucket.org/testillano/anna
+// http://redmine.teslayout.com/projects/anna-suite
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
-// * Neither the name of Google Inc. nor the names of its
+// * Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// cisco.tierra@gmail.com
-/*
- Establece un manejador externo para controlar el teclado, recoge los parametros de la operacion
- por este y envia la peticion al servidor.
-*/
-#include <iostream>
#include <fstream>
+#include <iostream>
+#include <time.h>
+#include <sys/stat.h> // chmod
+#include <fcntl.h> // open / write
#include <string>
#include <map>
#include <anna/http/functions.hpp>
#include <anna/comm/functions.hpp>
#include <anna/timex/Engine.hpp>
+#include <anna/timex/Clock.hpp>
#include <anna/diameter/stack/Engine.hpp>
#include <anna/diameter/codec/Engine.hpp>
#include <anna/diameter.comm/OamModule.hpp>
namespace comm {
class Entity;
class Response;
+class LocalServer;
}
}
}
anna::diameter::comm::Message G_commMsgSent2c, G_commMsgSent2e, G_commMsgFwd2c, G_commMsgFwd2e;
anna::diameter::comm::Message G_commMsg;
anna::diameter::codec::Message G_codecMsg, G_codecAnsMsg;
-anna::Recycler<anna::diameter::comm::Message> G_commMessages; // create en el forward de requets sin answer programada
-// realease en el forward de answers
+anna::Recycler<anna::diameter::comm::Message> G_commMessages; // create on requests forwards without programmed answer / release in answers forward
// Auxiliary resources for answers programming
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// COUNTERS RECORD PROCEDURE //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+class MyCounterRecorderClock : public anna::timex::Clock {
+ public:
+ MyCounterRecorderClock(const char *clockName, const anna::Millisecond & timeout) :
+ anna::timex::Clock(clockName, timeout) {;}
+ //virtual ~MyCounterRecorderClock();
+
+ virtual bool tick() throw (RuntimeException) {
+ anna::diameter::comm::OamModule::instantiate().recordCounters();
+ anna::diameter::codec::OamModule::instantiate().recordCounters();
+ return true;
+ }
+};
+
+class MyCounterRecorder : public anna::oam::CounterRecorder {
+
+ // attributes
+ int a_stream;
+ std::string a_fileNamePrefix;
+ std::string a_fileName;
+ time_t a_previousTime;
+ std::string a_fixedLine;
+
+ // pure virtual definitions:
+ void open() throw(anna::RuntimeException) {
+ static char str [256];
+
+ const time_t now = ::time (NULL);
+ struct tm tmNow;
+ struct tm tmPrevious;
+
+ anna_memcpy (&tmNow, localtime (&now), sizeof (tmNow));
+ anna_memcpy (&tmPrevious, localtime (&a_previousTime), sizeof (tmPrevious));
+
+ sprintf (
+ str,".Date%04d%02d%02d.Time%02d%02d%02d",
+ 1900 + (tmNow.tm_year), (tmNow.tm_mon) + 1,
+ tmNow.tm_mday, tmNow.tm_hour, tmNow.tm_min, tmNow.tm_sec);
+
+ a_fileName = a_fileNamePrefix;
+ a_fileName += str;
+
+ LOGDEBUG (
+ std::string msg ("Flush counters | ");
+ msg += a_fileName;
+ anna::Logger::debug(msg, ANNA_FILE_LOCATION);
+ );
+
+ if ((a_stream = ::open (a_fileName.c_str (), O_WRONLY | O_CREAT, S_IWUSR)) == -1)
+ throw RuntimeException (anna::functions::asString("Error opening file '%s'; errno = %d", a_fileName.c_str(), errno), ANNA_FILE_LOCATION);
+
+ sprintf (str, "%04d-%02d-%02d %02d:%02d|%04d-%02d-%02d %02d:%02d",
+ 1900 + (tmPrevious.tm_year), (tmPrevious.tm_mon) + 1,
+ tmPrevious.tm_mday, tmPrevious.tm_hour, tmPrevious.tm_min,
+ 1900 + (tmNow.tm_year), (tmNow.tm_mon) + 1,
+ tmNow.tm_mday, tmNow.tm_hour, tmNow.tm_min
+ );
+
+ a_fixedLine = str;
+ }
+
+
+ void apply(const anna::oam::Counter& counter) throw(anna::RuntimeException) {
+ static char line [356];
+ anna::oam::Counter::type_t value = counter;
+ sprintf (line, "%s|%06d|%07u|%s\n", a_fixedLine.c_str (), counter.getReference(), value, counter.getName ().c_str ());
+ if (write (a_stream, line, anna_strlen (line)) == -1)
+ throw RuntimeException (anna::functions::asString("Error writting to file '%s'; errno = %d", a_fileName.c_str(), errno), ANNA_FILE_LOCATION);
+ }
+
+ void close() throw() {
+ if (a_stream != -1) {
+ ::close (a_stream);
+ a_stream = -1;
+ }
+ chmod (a_fileName.c_str (), S_IWUSR | S_IRUSR);
+ a_previousTime = ::time (NULL);
+ }
+
+ std::string asString() const throw() {
+ std::string result = "Physical counters dump at file '";
+ result += a_fileName;
+ result += "'. Another way to see counters: context dump (kill -10 <pid>";
+ return result;
+ }
+
+ public:
+ MyCounterRecorder(const std::string &fnp) : a_stream(-1), a_fileNamePrefix(fnp) {
+ a_previousTime = ::time (NULL);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
class MyDiameterEntity : public anna::diameter::comm::Entity {
void eventResponse(const anna::diameter::comm::Response&) throw(anna::RuntimeException);
void eventBreakConnection(Server* server) throw();
};
-
-class MyCounterRecorder : public anna::oam::CounterRecorder {
-
- // pure virtual definitions:
- void open() throw(anna::RuntimeException) {;}
- void apply(const anna::oam::Counter& counter) throw(anna::RuntimeException) {;}
- void close() throw() {;}
- std::string asString() const throw() { return "Physical dump not implemented: see memory accumulations writting context (kill -10 <pid>)"; }
-};
-
-
class Launcher : public anna::comm::Application {
MyCommunicator *a_communicator;
anna::time::Date a_start_time;
anna::timex::Engine* a_timeEngine;
MyCounterRecorder *a_counterRecorder;
+ MyCounterRecorderClock *a_counterRecorderClock;
std::string a_cerPathfile;
std::string a_dwrPathfile;
std::string programmedAnswers2e() const throw();
std::string programmedAnswers2c() const throw();
+ // helpers
+ bool getDataBlockFromHexFile(const std::string &pathfile, anna::DataBlock &db) const throw();
+
// Burst feature
int clearBurst() throw(); // returns removed
int loadBurstMessage(const anna::DataBlock & db) throw(anna::RuntimeException);
std::string gotoBurst(int order) throw();
};
+bool Launcher::getDataBlockFromHexFile(const std::string &pathfile, anna::DataBlock &db) const throw() {
+
+ // Get hex string
+ static char buffer[2048];
+ std::ifstream infile(pathfile.c_str(), std::ifstream::in);
+ if(infile.is_open()) {
+ infile >> buffer;
+ std::string hexString(buffer, strlen(buffer));
+ anna::functions::fromHexString(hexString, db);
+ // Close file
+ infile.close();
+ return true;
+ }
+
+ return false;
+}
+
int Launcher::clearBurst() throw() {
int size = a_burstMessages.size();
result += "\nanswerxml|[source_file] Same as 'answerxml2c'.";
result += "\n List programmed answers if no parameter provided.";
result += "\n";
+ result += "\nSend operations are available using hexadecimal content (hex formatted files) which also allow to test";
+ result += "\nspecial scenarios (protocol errors):";
+ result += "\n";
+ result += "\nsendhex2e|<source_file> Sends hex source file (pathfile) through configured entity.";
+ result += "\nsendhex2c|<source_file> Sends hex source file (pathfile) to client.";
+ result += "\nsendhex|<source_file> Same as 'sendhex2e'.";
+ result += "\n";
+ result += "\nAnswer programming in hexadecimal is not really neccessary (you could use send primitives) and also";
+ result += "\nis intended to be used with decoded messages in order to replace things like hop by hop, end to end,";
+ result += "\nsubscriber id, session id, etc.";
+ result += "\n";
result += "\nIf a request is received, answer map (built with 'answerxml<[2c] or 2e>' operations) will be";
result += "\n checked to find a corresponding programmed answer to be replied(*). If no ocurrence is found,";
result += "\n or answer message was received, the message is forwarded to the other side (entity or client),";
result += "\n";
result += "\n(*) sequence values (hop-by-hop and end-to-end), Session-Id and Subscription-Id avps, are mirrored";
result += "\n to the peer which sent the request. If user wants to test a specific answer without changing it,";
- result += "\n use sendxml operations better than programming.";
+ result += "\n use sendxml/sendhex operations better than programming.";
result += "\n";
result += "\nBalance ('-balance' command line parameter) could be used to forward server socket receptions through";
result += "\n entity servers by mean a round-robin algorithm. Both diameter server socket and entity targets should";
commandLine.add("detailedLog", anna::CommandLine::Argument::Optional, "Insert detailed information at log files. Should be disabled on automatic tests. Useful on '-balance' mode to know messages flow along the sockets", false);
commandLine.add("logStatisticSamples", anna::CommandLine::Argument::Optional, "Log statistics samples for the provided concept id list, over './sample.<concept id>.csv' files. For example: \"1,2\" will log concepts 1 and 2. Reserved word \"all\" activates all registered statistics concept identifiers. That ids are shown at context dump (see help to get it).");
commandLine.add("burstLog", anna::CommandLine::Argument::Optional, "Burst operations log file. By default 'launcher.burst'. Empty string or \"null\" name, to disable. Warning: there is no rotation for log files (use logrotate or whatever). Output: dot (.) for each burst message sent/pushed, cross (x) for popped ones, and order number when multiple of 1% of burst list size, plus OTA requests when changed.");
+ commandLine.add("cntDir", anna::CommandLine::Argument::Optional, "Counters directory. By default is the current execution directory. Warning: a counter file will be dump per record period; take care about the possible accumulation of files");
+ commandLine.add("cntRecordPeriod", anna::CommandLine::Argument::Optional, "Counters record procedure period in milliseconds. If missing, default value of 300000 (5 minutes) will be assigned. Value of 0 disables the record procedure.");
// Communications
commandLine.add("httpServer", anna::CommandLine::Argument::Optional, "HTTP Management interface address (using i.e. curl tool) in '<address>:<port>' format. For example: 10.20.30.40:8080");
commandLine.add("httpServerShared", anna::CommandLine::Argument::Optional, "Enables shared bind for HTTP Management interface address. It would be useful i.e. to allow a great amount of curl operations per second", false);
a_detailedLog = false;
a_timeEngine = NULL;
a_counterRecorder = NULL;
+ a_counterRecorderClock = NULL;
a_entity = NULL;
a_diameterLocalServer = NULL;
a_cerPathfile = "cer.xml";
if (a_detailedLog) {
anna::time::Date now;
- now.setCurrent();
+ now.setNow();
title += " ";
title += now.asString();
log += anna::functions::highlight(title, anna::functions::TextHighlightMode::OverAndUnderline);
void Launcher::checkTimeMeasure(const char * commandLineParameter, bool optional) throw(anna::RuntimeException) {
CommandLine& cl(anna::CommandLine::instantiate());
- if (!cl.exists(commandLineParameter) && optional) return; // si fuese obligatorio daria error de arranque.
+ if (!cl.exists(commandLineParameter) && optional) return; // start error if mandatory
std::string parameter = cl.getValue(commandLineParameter);
// workMode = anna::comm::Communicator::WorkMode::Clone;
a_communicator = new MyCommunicator(workMode);
a_timeEngine = new anna::timex::Engine((anna::Millisecond)300000, (anna::Millisecond)150);
- a_counterRecorder = new MyCounterRecorder();
+
+ // Counters record procedure:
+ anna::Millisecond cntRecordPeriod = (anna::Millisecond)300000; // ms
+ if (cl.exists("cntRecordPeriod")) cntRecordPeriod = cl.getIntegerValue("cntRecordPeriod");
+ if (cntRecordPeriod != 0) {
+ checkTimeMeasure("cntRecordPeriod");
+ a_counterRecorderClock = new MyCounterRecorderClock("Counters record procedure clock", cntRecordPeriod); // clock
+
+ std::string cntDir = ".";
+ if (cl.exists("cntDir")) cntDir = cl.getValue("cntDir");
+ a_counterRecorder = new MyCounterRecorder(cntDir + anna::functions::asString("/Counters.Pid%d", (int)getPid()));
+ }
}
void Launcher::run()
LOGMETHOD(anna::TraceMethod tm("Launcher", "run", ANNA_FILE_LOCATION));
CommandLine& cl(anna::CommandLine::instantiate());
// Start time:
- a_start_time.setCurrent();
+ a_start_time.setNow();
// Statistics:
anna::statistics::Engine::instantiate().enable();
///////////////////////////////
oamDiameterComm.initializeCounterScope(1); // 1000 - 1999
anna::diameter::codec::OamModule & oamDiameterCodec = anna::diameter::codec::OamModule::instantiate();
oamDiameterCodec.initializeCounterScope(2); // 2000 - 2999
+
/////////////////
// COMM MODULE //
/////////////////
oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FailedRuleForCardinalityMoreThanNeeded, "", 17 /*2017*/);
oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FailedGenericAvpRuleForCardinalityFoundDisregardedItem, "", 18 /*2018*/);
oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FoundDisregardedItemsAndGenericAVPWasNotSpecified, "", 19 /*2019*/);
- anna::oam::CounterManager& cm = anna::oam::CounterManager::instantiate();
- cm.setEngine(a_timeEngine);
- cm.setRecordPeriod(Millisecond(300000));
- cm.setCounterRecorder(static_cast<anna::oam::CounterRecorder*>(a_counterRecorder));
+
+ /////////////////////////////////
+ // Counter recorder associated //
+ /////////////////////////////////
+ if (a_counterRecorderClock) {
+ oamDiameterComm.setCounterRecorder(a_counterRecorder);
+ oamDiameterCodec.setCounterRecorder(a_counterRecorder);
+ a_timeEngine->activate(a_counterRecorderClock); // start clock
+ }
// Checking command line parameters
if (cl.exists("sessionBasedModelsClientSocketSelection")) {
LOGDEBUG(anna::Logger::debug(operation, ANNA_FILE_LOCATION));
response_content = "Operation processed with exception. See traces\n"; // supposed
std::string result = "";
+ anna::DataBlock db_aux(true);
+
+ ///////////////////////////////////////////////////////////////////
+ // Simple operations without arguments:
// Help:
if (operation == "help") {
response_content = "All process counters & statistic information have been reset\n";
return;
}
+ ///////////////////////////////////////////////////////////////////
// Tokenize operation
Tokenizer params;
params.apply(operation, "|");
int numParams = params.size() - 1;
- //LOGDEBUG(anna::Logger::debug(anna::functions::asString("Number of operation parameters: %d", numParams), ANNA_FILE_LOCATION));
+ // No operation has more than 2 arguments ...
if (numParams > 2) {
LOGWARNING(anna::Logger::warning(help(), ANNA_FILE_LOCATION));
throw anna::RuntimeException("Wrong body content format on HTTP Request", ANNA_FILE_LOCATION);
}
+ // Get the operation type:
Tokenizer::const_iterator tok_iter = params.begin();
std::string opType = Tokenizer::data(tok_iter);
- std::string param1, param2;
- if (numParams >= 1) { tok_iter++; param1 = Tokenizer::data(tok_iter); }
+ // Check the number of parameters:
+ bool wrongBody = false;
+ if ( ((opType == "code")||(opType == "decode")) && (numParams != 2) ) wrongBody = true;
+ if ( ((opType == "sendxml") || (opType == "sendxml2e") || (opType == "sendhex") || (opType == "sendhex2e")) && (numParams != 1) ) wrongBody = true;
+ if ( (opType == "burst") && (numParams < 1) ) wrongBody = true;
+ if ( ((opType == "sendxml2c")||(opType == "sendhex2c")||(opType == "loadxml")||(opType == "diameterServerSessions")) && (numParams != 1) ) wrongBody = true;
+ if (wrongBody) {
+ // Launch exception
+ std::string msg = "Wrong body content format on HTTP Request for '";
+ msg += opType;
+ msg += "' operation (missing parameter/s)";
+ throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
+ }
+ // All seems ok:
+ std::string param1, param2;
+ if (numParams >= 1) { tok_iter++; param1 = Tokenizer::data(tok_iter); }
if (numParams == 2) { tok_iter++; param2 = Tokenizer::data(tok_iter); }
- if (opType == "code") {
- if (numParams != 2)
- throw anna::RuntimeException("Wrong body content format on HTTP Request for 'code' operation (missing parameter/s)", ANNA_FILE_LOCATION);
+ // Operations:
+ if (opType == "code") {
G_codecMsg.loadXML(param1);
std::string hexString = anna::functions::asHexString(G_codecMsg.code());
// write to outfile
ofstream outfile(param2.c_str(), ifstream::out);
outfile.write(hexString.c_str(), hexString.size());
outfile.close();
- } else if (opType == "decode") {
- if (numParams != 2)
- throw anna::RuntimeException("Wrong body content format on HTTP Request for 'decode' operation (missing parameter/s)", ANNA_FILE_LOCATION);
- char buffer[2048];
- ifstream infile(param1.c_str(), ifstream::in);
- infile >> buffer;
- std::string hexString(buffer, strlen(buffer));
- anna::DataBlock db(true);
- anna::functions::fromHexString(hexString, db);
+ } else if (opType == "decode") {
+ // Get DataBlock from file with hex content:
+ if (!getDataBlockFromHexFile(param1, db_aux))
+ throw anna::RuntimeException("Error reading hex file provided", ANNA_FILE_LOCATION);
// Decode
- try { G_codecMsg.decode(db); } catch (anna::RuntimeException &ex) { ex.trace(); }
+ try { G_codecMsg.decode(db_aux); } catch (anna::RuntimeException &ex) { ex.trace(); }
std::string xmlString = G_codecMsg.asXMLString();
// write to outfile
ofstream outfile(param2.c_str(), ifstream::out);
outfile.write(xmlString.c_str(), xmlString.size());
outfile.close();
- infile.close();
+
} else if ((opType == "hide") || (opType == "show") || (opType == "hidden") || (opType == "shown")) {
anna::diameter::comm::Entity *entity = getEntity();
-
if (!entity) throw anna::RuntimeException("No entity configured to send messages", ANNA_FILE_LOCATION);
-
if (param1 != "") {
if (param2 != "") {
std::string key = param1;
key += param2;
if (opType == "hide") getMyDiameterEngine()->findClientSession(key)->hide();
-
if (opType == "show") getMyDiameterEngine()->findClientSession(key)->show();
-
if (opType == "hidden") result = getMyDiameterEngine()->findClientSession(key)->hidden() ? "true" : "false";
-
if (opType == "shown") result = getMyDiameterEngine()->findClientSession(key)->shown() ? "true" : "false";
} else {
std::string address;
anna::functions::getAddressAndPortFromSocketLiteral(param1, address, port);
if (opType == "hide") getMyDiameterEngine()->findServer(address, port)->hide();
-
if (opType == "show") getMyDiameterEngine()->findServer(address, port)->show();
-
if (opType == "hidden") result = getMyDiameterEngine()->findServer(address, port)->hidden() ? "true" : "false";
-
if (opType == "shown") result = getMyDiameterEngine()->findServer(address, port)->shown() ? "true" : "false";
}
} else {
if (opType == "hide") entity->hide();
-
if (opType == "show") entity->show();
-
if (opType == "hidden") result = entity->hidden() ? "true" : "false";
-
if (opType == "shown") result = entity->shown() ? "true" : "false";
}
- } else if ((opType == "sendxml") || (opType == "sendxml2e")) {
- if (numParams != 1)
- throw anna::RuntimeException("Wrong body content format on HTTP Request for 'sendxml/sendxml2e' operation (missing parameter)", ANNA_FILE_LOCATION);
+ } else if ((opType == "sendxml") || (opType == "sendxml2e") || (opType == "sendhex") || (opType == "sendhex2e")) {
anna::diameter::comm::Entity *entity = getEntity();
-
if (!entity) throw anna::RuntimeException("No entity configured to send the message", ANNA_FILE_LOCATION);
- G_codecMsg.loadXML(param1);
- G_commMsgSent2e.clearBody();
- try { G_codecMsg.valid(); } catch (anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue sending (see validation mode configured in launcher)
+ if ((opType == "sendxml") || (opType == "sendxml2e")) {
+ G_codecMsg.loadXML(param1);
+ G_commMsgSent2e.clearBody();
+ try { G_codecMsg.valid(); } catch (anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue sending (see validation mode configured in launcher)
+ G_commMsgSent2e.setBody(G_codecMsg.code());
+ }
+ else {
+ // Get DataBlock from file with hex content:
+ if (!getDataBlockFromHexFile(param1, db_aux))
+ throw anna::RuntimeException("Error reading hex file provided", ANNA_FILE_LOCATION);
+ G_commMsgSent2e.setBody(db_aux);
+ }
- G_commMsgSent2e.setBody(G_codecMsg.code());
bool success = entity->send(G_commMsgSent2e, cl.exists("balance"));
// Detailed log:
writeLogFile(G_codecMsg, (success ? "sent2e" : "send2eError"), detail);
}
} else if ((opType == "burst")) {
- if (numParams < 1)
- throw anna::RuntimeException("Wrong body content format on HTTP Request for 'burst' operation (missing action parameter)", ANNA_FILE_LOCATION);
-
anna::diameter::comm::Entity *entity = getEntity();
-
if (!entity) throw anna::RuntimeException("No entity configured to use burst feature", ANNA_FILE_LOCATION);
// burst|clear clears all loaded burst messages.
} else {
throw anna::RuntimeException("Wrong body content format on HTTP Request for 'burst' operation (unexpected action parameter). See help", ANNA_FILE_LOCATION);
}
- } else if (opType == "sendxml2c") {
- if (numParams != 1)
- throw anna::RuntimeException("Wrong body content format on HTTP Request for 'sendxml2c' operation (missing parameter)", ANNA_FILE_LOCATION);
+ } else if ((opType == "sendxml2c") || (opType == "sendhex2c")) {
anna::diameter::comm::LocalServer *localServer = getDiameterLocalServer();
-
if (!localServer) throw anna::RuntimeException("No local server configured to send the message", ANNA_FILE_LOCATION);
- G_codecMsg.loadXML(param1);
- G_commMsgSent2c.clearBody();
- try { G_codecMsg.valid(); } catch (anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue sending (see validation mode configured in launcher)
+ if (opType == "sendxml2c") {
+ G_codecMsg.loadXML(param1);
+ G_commMsgSent2c.clearBody();
+ try { G_codecMsg.valid(); } catch (anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue sending (see validation mode configured in launcher)
+ G_commMsgSent2c.setBody(G_codecMsg.code());
+ }
+ else {
+ // Get DataBlock from file with hex content:
+ if (!getDataBlockFromHexFile(param1, db_aux))
+ throw anna::RuntimeException("Error reading hex file provided", ANNA_FILE_LOCATION);
+ G_commMsgSent2c.setBody(db_aux);
+ }
- G_commMsgSent2c.setBody(G_codecMsg.code());
bool success = localServer->send(G_commMsgSent2c);
// Detailed log:
std::string detail = usedServerSession ? usedServerSession->asString() : "<null server session>"; // esto no deberia ocurrir
writeLogFile(G_codecMsg, (success ? "sent2c" : "send2cError"), detail);
}
- } else if (opType == "loadxml") {
- if (numParams != 1)
- throw anna::RuntimeException("Wrong body content format on HTTP Request for 'loadxml' operation (missing parameter)", ANNA_FILE_LOCATION);
+ } else if (opType == "loadxml") {
G_codecMsg.loadXML(param1);
std::string xmlString = G_codecMsg.asXMLString();
std::cout << xmlString << std::endl;
+
} else if (opType == "diameterServerSessions") {
- if (numParams != 1)
- throw anna::RuntimeException("Wrong body content format on HTTP Request for 'diameterServerSessions' operation (missing parameter)", ANNA_FILE_LOCATION);
int diameterServerSessions = atoi(param1.c_str());
response_content = "Programmed answers dumped on stdout\n";
return;
}
- } else if ((opType == "answerxml2e")) {
+ } else if (opType == "answerxml2e") {
anna::diameter::comm::Entity *entity = getEntity();
if (!entity)
response_content += "Result: ";
response_content += result;
response_content += "\n";
- } else if ((opType == "sendxml") || (opType == "sendxml2e")) {
+ } else if ((opType == "sendxml") || (opType == "sendxml2e") || (opType == "sendhex") || (opType == "sendhex2e")) {
response_content += "Message '";
response_content += param1;
response_content += "' sent to entity.";
response_content += "' executed. ";
response_content += result;
response_content += "\n";
- } else if (opType == "sendxml2c") {
+ } else if ((opType == "sendxml2c")||(opType == "sendhex2c")) {
response_content += "Message '";
response_content += param1;
response_content += "' sent to client.";
response_content += param1;
response_content += "' programmed.";
response_content += "\n";
- } else if ((opType == "answerxml2e")) {
+ } else if (opType == "answerxml2e") {
response_content += "Answer to entity '";
response_content += param1;
response_content += "' programmed.";