<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<!-- Diameter services DTD -->\n\
\n\
-<!ELEMENT services (stack*, node*)>\n\
+<!ELEMENT services ((stack*, node*)|(node*, stack*))>\n\
\n\
<!ELEMENT stack EMPTY>\n\
<!ATTLIST stack id CDATA #REQUIRED dictionary CDATA #REQUIRED validationMode (BeforeEncoding | AfterDecoding | Always | Never) #IMPLIED validationDepth (Complete | FirstError) #IMPLIED fixMode (BeforeEncoding | AfterDecoding | Always | Never) #IMPLIED ignoreFlagsOnValidation (yes | no) #IMPLIED>\n\
a_counterRecorderClock = NULL;
a_workingNode = NULL;
+ a_operatedHost = NULL;
a_httpServerSocket = NULL;
}
std::string Launcher::getSignalUSR2InputFile() const throw() {
- return (a_initialWorkingDirectory + "/" + SIGUSR2_TASKS_INPUT_FILENAME);
+ return (getInitialWorkingDirectory() + "/" + SIGUSR2_TASKS_INPUT_FILENAME);
}
std::string Launcher::getSignalUSR2OutputFile() const throw() {
- return (a_initialWorkingDirectory + "/" + SIGUSR2_TASKS_OUTPUT_FILENAME);
+ return (getInitialWorkingDirectory() + "/" + SIGUSR2_TASKS_OUTPUT_FILENAME);
}
-void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOperation) throw(anna::RuntimeException) {
+void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool bindResources) throw(anna::RuntimeException) {
CommandLine& cl(anna::CommandLine::instantiate());
bool allLogsDisabled = cl.exists("disableLogs");
// We will register a scope per stack id registered. The counters will be dynamically registered at count method.
anna::diameter::comm::ApplicationMessageOamModule & appMsgOamModule = anna::diameter::comm::ApplicationMessageOamModule::instantiate();
appMsgOamModule.enableCounters(); // this special module is disabled by default (the only)
- static int scope_id = 3;
+ static int scope_id = 3 + appMsgOamModule.scopes();
+
unsigned int id_value;
std::string codecEngineName;
if (stackEngine.getDictionary(id_value)) { // Ignore (but don't fail) dictionary load with same stack id already registered
LOGWARNING(anna::Logger::warning(anna::functions::asString("Ignore dictionary load for stack id already registered: %llu", id_value), ANNA_FILE_LOCATION));
+ // Delta loads, in case we provide base protocol already registered (comm::Engine will need 'bpd')
+ if (id_value == 0)
+ bpd = stackEngine.getDictionary(0);
continue;
}
a_workingNode->createEntity(entity->getValue(), ceaTimeoutMs, answersTimeoutMs);
a_workingNode->getEntity()->setSessionBasedModelsType(sessionBasedModelsTypeEnum);
a_workingNode->getEntity()->setBalance(balance ? (balance->getValue() == "yes") : false); // for sendings
- if (eventOperation) a_workingNode->getEntity()->bind();
+ if (bindResources) a_workingNode->getEntity()->bind();
}
}
// Lazy initialization for comm engine:
- if (eventOperation) commEngine->lazyInitialize();
+ if (bindResources) commEngine->lazyInitialize();
// Node and Codec Engine registration ///////////////////////////////////////////////////////
ohm.registerOriginHost(originHost->getValue(), a_workingNode);
}
-void Launcher::loadServices(const std::string & xmlPathFile, bool eventOperation) throw(anna::RuntimeException) {
+void Launcher::loadServicesFromFile(const std::string & xmlPathFile, bool bindResources) throw(anna::RuntimeException) {
if (xmlPathFile == "null" || xmlPathFile == "") {
LOGWARNING(anna::Logger::warning("Ignoring services configuration on start: empty or 'null' string provided as xml file. Use management interface (operation 'services') in order to add services", ANNA_FILE_LOCATION));
trace += anna::xml::Compiler().apply(rootNode);
anna::Logger::debug(trace, ANNA_FILE_LOCATION);
);
- servicesFromXML(rootNode, eventOperation);
+ servicesFromXML(rootNode, bindResources);
+}
+
+
+void Launcher::loadServicesFromXMLString(const std::string & xmlString, bool bindResources) throw(anna::RuntimeException) {
+
+ anna::xml::DocumentMemory xmlDocument; // has private copy constructor defined but not implemented to avoid inhenrit/copy (is very heavy)
+ anna::xml::DTDMemory xmlDTD;
+ const anna::xml::Node *rootNode;
+ xmlDocument.initialize(xmlString.c_str());
+ xmlDTD.initialize(ServicesDTD);
+ try {
+ rootNode = xmlDocument.parse(xmlDTD); // Parsing: fail here if xml violates dtd
+ }
+ catch (anna::RuntimeException &ex) {
+ LOGWARNING(
+ std::string msg = "Services DTD schema:\n\n";
+ msg += ServicesDTD;
+ anna::Logger::warning(msg, ANNA_FILE_LOCATION);
+ );
+ throw ex;
+ }
+
+ LOGDEBUG(
+ std::string trace = "Loaded XML String:\n";
+ trace += anna::xml::Compiler().apply(rootNode);
+ anna::Logger::debug(trace, ANNA_FILE_LOCATION);
+ );
+ servicesFromXML(rootNode, bindResources);
}
return (getOriginHost(originHost));
}
+anna::diameter::comm::OriginHost *Launcher::getOriginHost(const anna::DataBlock &messageDataBlock) const throw(anna::RuntimeException) {
+ std::string originHost = anna::diameter::helpers::base::functions::getOriginHost(messageDataBlock);
+ return (getOriginHost(originHost));
+}
+
bool Launcher::uniqueOriginHost() const throw() {
anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
return (ohm.size() == 1);
}
-
void Launcher::updateOperatedOriginHostWithMessage(const anna::diameter::codec::Message &message) throw(anna::RuntimeException) {
if (!a_operatedHost) // priority for working node by mean 'node' operation
a_operatedHost = getOriginHost(message);
}
+void Launcher::updateOperatedOriginHostWithMessage(const anna::DataBlock &messageDataBlock) throw(anna::RuntimeException) {
+ if (!a_operatedHost) // priority for working node by mean 'node' operation
+ a_operatedHost = getOriginHost(messageDataBlock);
+}
+
anna::diameter::comm::OriginHost *Launcher::getWorkingNode() const throw(anna::RuntimeException) {
if(!a_workingNode)
throw anna::RuntimeException("Working node not identified (try to load services)", ANNA_FILE_LOCATION);
return a_operatedHost;
}
+void Launcher::setOperatedHost(anna::diameter::comm::OriginHost *op) {
+ a_operatedHost = op;
+}
+
MyDiameterEntity *Launcher::getOperatedEntity() const throw(anna::RuntimeException) {
MyDiameterEntity *result = (MyDiameterEntity *)(getOperatedHost()->getEntity());
if (!result)
anna::Logger::setLevel(anna::Logger::asLevel(cl.getValue("trace")));
// Load launcher services:
- loadServices(cl.getValue("services")); // before run (have components to be created)
+ loadServicesFromFile(cl.getValue("services"), false /* no bind at the moment */); // before run (have components to be created)
}
void Launcher::run()
}
-bool Launcher::eventOperation(const std::string &operation, std::string &response_content) throw(anna::RuntimeException) {
+bool Launcher::eventOperation(const std::string &operation, std::string &response) throw(anna::RuntimeException) {
bool result = true;
if (operation == "") return result; // ignore
LOGDEBUG(anna::Logger::debug(anna::functions::asString("Operation: %s", operation.c_str()), ANNA_FILE_LOCATION));
+ EventOperation eop(false /* not HTTP, it is SIGUSR2 */);
+
// Default response:
- response_content = "Operation processed with exception: ";
- response_content += operation;
- std::string opt_response_content = ""; // aditional response content
+ //response = "Operation processed with exception: ";
+ response = "Internal error (check ADML traces): ";
+ response += operation;
+ std::string opt_response = ""; // aditional response content
anna::DataBlock db_aux(true);
anna::diameter::codec::Message codecMsg; // auxiliary codec message
if (args == "" && op_size != 7)
throw anna::RuntimeException("Wrong body content format on HTTP Request. Check 'HELP.md' for more information.", ANNA_FILE_LOCATION);
try {
- p.execute(args, response_content);
+ p.execute(args, response);
}
catch(anna::RuntimeException &ex) {
ex.trace();
- response_content = ex.asString();
+ response = ex.asString();
return false;
}
return true; // OK
// Reset performance data:
if(operation == "collect") {
- resetCounters();
- resetStatistics();
- response_content = "All process counters & statistic information have been reset";
- return true; // OK
+ return eop.collect(response);
}
// Counters dump on demand:
if(operation == "forceCountersRecord") {
- forceCountersRecord();
- response_content = "Current counters have been dump to disk";
- return true; // OK
+ return eop.forceCountersRecord(response);
}
// OAM & statistics:
if(operation == "show-oam") {
- anna::xml::Node root("root");
- response_content = anna::xml::Compiler().apply(oamAsXML(&root));
- return true; // OK
+ return eop.show_oam(response);
}
if(operation == "show-stats") {
- anna::xml::Node root("root");
- response_content = anna::xml::Compiler().apply(statsAsXML(&root));
- return true; // OK
+ return eop.show_stats(response);
}
///////////////////////////////////////////////////////////////////
if((opType == "log-statistics-samples") && (numParams != 1)) wrongBody = true;
if((opType == "node") && (numParams > 1)) wrongBody = true;
- if((opType == "node_auto") && (numParams > 0)) wrongBody = true;
+ if((opType == "node-auto") && (numParams > 0)) wrongBody = true;
if(((opType == "code") || (opType == "decode")) && (numParams != 2)) wrongBody = true;
// Operations:
if(opType == "context") {
- std::string contextFile = ((numParams == 1) ? param1 : anna::functions::asString("/var/tmp/anna.context.%05d", getPid()));
- writeContext(contextFile);
- response_content = anna::functions::asString("Context dumped on file '%s'", contextFile.c_str());
- return true; // OK
+ return eop.context(response, (numParams == 1) ? param1 : "");
}
if(opType == "log-statistics-samples") {
- logStatisticsSamples(param1);
- response_content = anna::functions::asString("Log statistics samples for '%s' concepts", param1.c_str());
- return true; // OK
+ return eop.log_statistics_samples(response, param1);
}
// Change execution directory:
if(opType == "change-dir") {
- if (param1 == "") param1 = a_initialWorkingDirectory;
- result = (chdir(param1.c_str()) == 0);
-
- if (result)
- response_content = "New execution directory configured: ";
- else
- response_content = "Cannot assign provided execution directory: ";
-
- response_content += param1;
- return result;
+ return eop.change_dir(response, param1);
}
if(opType == "services") {
std::string servicesFile = ((numParams == 1) ? param1 : "services.xml");
try {
- loadServices(servicesFile, true /* bind entities */);
+ loadServicesFromFile(servicesFile, true /* bind entities */);
}
catch(anna::RuntimeException &ex) {
ex.trace();
- response_content = anna::functions::asString("Loaded services from file '%s' with errors", servicesFile.c_str());
+ response = anna::functions::asString("Loaded services from file '%s' with errors", servicesFile.c_str());
return false;
}
- response_content = anna::functions::asString("Loaded services from file '%s'", servicesFile.c_str());
+ response = anna::functions::asString("Loaded services from file '%s'", servicesFile.c_str());
return true; // OK
}
// Host switch:
if(opType == "node") {
- if (param1 != "") {
- if (setWorkingNode(param1)) response_content = anna::functions::asString("Forced node is now '%s'", param1.c_str());
- }
- else {
- if (a_workingNode) {
- response_content = "Working node is forced to be: \n\n";
- response_content += a_workingNode->asXMLString();
- }
- else {
- response_content = "Working node is automatic";
- }
- }
- return true; // OK
+ return eop.node(response, param1);
}
- if(opType == "node_auto") {
- a_workingNode = NULL;
- response_content = "Working node has been set to automatic";
- return true; // OK
+ else if(opType == "node-auto") {
+ return eop.node_auto(response);
}
- // Operated host from possible forced-working node:
- a_operatedHost = a_workingNode ? a_workingNode /* priority */: NULL /* auto */;
- // Use later:
- // If any message is managed: updateOperatedOriginHostWithMessage(codecMessage)
- // To operate, use the exception-protected methods which never will return NULL:
- // getOperatedHost(), getOperatedEntity(), getOperatedServer(), getOperatedEngine()
-
-
if(opType == "code") {
codecMsg.loadXMLFile(param1);
std::string hexString = anna::functions::asHexString(codecMsg.code());
outfile.write(xmlString.c_str(), xmlString.size());
outfile.close();
} else if((opType == "hide") || (opType == "show") || (opType == "hidden") || (opType == "shown")) {
+ result = eop.visibility(opt_response, opType, param1, (param2 != "") ? atoi(param2.c_str()) : -1);
- if(param1 != "") {
- if(param2 != "") {
- std::string key = param1;
- key += "|";
- key += param2;
-
- if(opType == "hide") getOperatedEngine()->findClientSession(key)->hide();
-
- if(opType == "show") getOperatedEngine()->findClientSession(key)->show();
-
- if(opType == "hidden") opt_response_content = getOperatedEngine()->findClientSession(key)->hidden() ? "true" : "false";
-
- if(opType == "shown") opt_response_content = getOperatedEngine()->findClientSession(key)->shown() ? "true" : "false";
- } else {
- std::string address;
- int port;
- anna::functions::getAddressAndPortFromSocketLiteral(param1, address, port);
-
- if(opType == "hide") getOperatedEngine()->findServer(address, port)->hide();
-
- if(opType == "show") getOperatedEngine()->findServer(address, port)->show();
-
- if(opType == "hidden") opt_response_content = getOperatedEngine()->findServer(address, port)->hidden() ? "true" : "false";
-
- if(opType == "shown") opt_response_content = getOperatedEngine()->findServer(address, port)->shown() ? "true" : "false";
- }
- } else {
- if(opType == "hide") getOperatedEntity()->hide();
-
- if(opType == "show") getOperatedEntity()->show();
-
- if(opType == "hidden") opt_response_content = getOperatedEntity()->hidden() ? "true" : "false";
-
- if(opType == "shown") opt_response_content = getOperatedEntity()->shown() ? "true" : "false";
- }
} else if((opType == "sendxml2e") || (opType == "sendhex2e")) {
anna::diameter::comm::Message *msg;
// Get DataBlock from file with hex content:
if(!getDataBlockFromHexFile(param1, db_aux))
throw anna::RuntimeException("Error reading hex file provided", ANNA_FILE_LOCATION);
+ updateOperatedOriginHostWithMessage(db_aux);
msg = getOperatedHost()->createCommMessage();
msg->setBody(db_aux);
try { if(getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); }
if(getOperatedHost()->logEnabled()) {
anna::diameter::comm::Server *usedServer = getOperatedEntity()->getLastUsedResource();
anna::diameter::comm::ClientSession *usedClientSession = usedServer ? usedServer->getLastUsedResource() : NULL;
- std::string detail = usedClientSession ? usedClientSession->asString() : "<null client session>"; // shouldn't happen
+ std::string detail = usedClientSession ? usedClientSession->asString() : "[null client session]"; // shouldn't happen
getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2e" : "send2eError"), detail);
}
+ } else if((opType == "sendxml2c") || (opType == "sendhex2c")) {
+ anna::diameter::comm::Message *msg;
+
+ if(opType == "sendxml2c") {
+ codecMsg.loadXMLFile(param1);
+ updateOperatedOriginHostWithMessage(codecMsg);
+ msg = getOperatedHost()->createCommMessage();
+ msg->clearBody();
+ try { 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)
+
+ msg->setBody(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);
+ updateOperatedOriginHostWithMessage(db_aux);
+ msg = getOperatedHost()->createCommMessage();
+ msg->setBody(db_aux);
+ }
+
+ bool success = getOperatedServer()->send(msg);
+ getOperatedHost()->releaseCommMessage(msg);
+
+ // Detailed log:
+ if(getOperatedHost()->logEnabled()) {
+ anna::diameter::comm::ServerSession *usedServerSession = getOperatedServer()->getLastUsedResource();
+ std::string detail = usedServerSession ? usedServerSession->asString() : "[null server session]"; // shouldn't happen
+ getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2c" : "send2cError"), detail);
+ }
+ } else if(opType == "answerxml2e") {
+
+ if(param1 == "") { // programmed answers FIFO's to stdout
+ response = getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY");
+ return true; // OK
+ } else if (param1 == "rotate") {
+ getOperatedEntity()->getReactingAnswers()->rotate(true);
+ } else if (param1 == "exhaust") {
+ getOperatedEntity()->getReactingAnswers()->rotate(false);
+ } else if (param1 == "clear") {
+ getOperatedEntity()->getReactingAnswers()->clear();
+ } else if (param1 == "dump") {
+ getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
+ } else {
+ codecMsg.loadXMLFile(param1);
+ updateOperatedOriginHostWithMessage(codecMsg);
+ anna::diameter::codec::Message *message = getOperatedHost()->getCodecEngine()->createMessage(param1); // loads xml again, lesser of two evils
+ LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
+
+ if(message->isRequest())
+ throw anna::RuntimeException("Cannot program diameter requests. Answer type must be provided", ANNA_FILE_LOCATION);
+
+ int code = message->getId().first;
+ LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to entity' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
+ getOperatedEntity()->getReactingAnswers()->addMessage(code, message);
+ }
+ } else if(opType == "answerxml2c") {
+
+ if(param1 == "") { // programmed answers FIFO's to stdout
+ response = getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT");
+ return true; // OK
+ } else if (param1 == "rotate") {
+ getOperatedServer()->getReactingAnswers()->rotate(true);
+ } else if (param1 == "exhaust") {
+ getOperatedServer()->getReactingAnswers()->rotate(false);
+ } else if (param1 == "clear") {
+ getOperatedServer()->getReactingAnswers()->clear();
+ } else if (param1 == "dump") {
+ getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
+ } else {
+ codecMsg.loadXMLFile(param1);
+ updateOperatedOriginHostWithMessage(codecMsg);
+ anna::diameter::codec::Message *message = getOperatedHost()->getCodecEngine()->createMessage(param1); // loads xml again, lesser of two evils
+ LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
+
+ if(message->isRequest())
+ throw anna::RuntimeException("Cannot program diameter requests. Answer type must be provided", ANNA_FILE_LOCATION);
+
+ int code = message->getId().first;
+ LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to client' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
+ getOperatedServer()->getReactingAnswers()->addMessage(code, message);
+ }
} else if((opType == "burst")) {
if (!uniqueOriginHost())
// burst|look|<order> Show programmed burst message for order provided, current when missing.
if(param1 == "clear") {
- opt_response_content = "removed ";
- opt_response_content += anna::functions::asString(getOperatedHost()->clearBurst());
- opt_response_content += " elements";
+ opt_response = "removed ";
+ opt_response += anna::functions::asString(getOperatedHost()->clearBurst());
+ opt_response += " elements";
} else if(param1 == "load") {
if(param2 == "") throw anna::RuntimeException("Missing xml path file for burst load operation", ANNA_FILE_LOCATION);
try { codecMsg.valid(); } catch(anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue loading (see validation mode configured in launcher)
int position = getOperatedHost()->loadBurstMessage(codecMsg.code());
- opt_response_content = "loaded '";
- opt_response_content += param2;
- opt_response_content += "' file into burst list position ";
- opt_response_content += anna::functions::asString(position);
+ opt_response = "loaded '";
+ opt_response += param2;
+ opt_response += "' file into burst list position ";
+ opt_response += anna::functions::asString(position);
} else if(param1 == "start") {
if(param2 == "") throw anna::RuntimeException("Missing initial load for burst start operation", ANNA_FILE_LOCATION);
int processed = getOperatedHost()->startBurst(initialLoad);
if(processed > 0) {
- opt_response_content = "initial load completed for ";
- opt_response_content += anna::functions::entriesAsString(processed, "message");
+ opt_response = "initial load completed for ";
+ opt_response += anna::functions::entriesAsString(processed, "message");
}
} else if(param1 == "push") {
if(param2 == "") throw anna::RuntimeException("Missing load amount for burst push operation", ANNA_FILE_LOCATION);
int pushed = getOperatedHost()->pushBurst(atoi(param2.c_str()));
if(pushed > 0) {
- opt_response_content = "pushed ";
- opt_response_content += anna::functions::entriesAsString(pushed, "message");
+ opt_response = "pushed ";
+ opt_response += anna::functions::entriesAsString(pushed, "message");
}
} else if(param1 == "pop") {
if(param2 == "") throw anna::RuntimeException("Missing amount for burst pop operation", ANNA_FILE_LOCATION);
int popped = getOperatedHost()->popBurst(releaseLoad);
if(popped > 0) {
- opt_response_content = "burst popped for ";
- opt_response_content += anna::functions::entriesAsString(popped, "message");
+ opt_response = "burst popped for ";
+ opt_response += anna::functions::entriesAsString(popped, "message");
}
} else if(param1 == "stop") {
int left = getOperatedHost()->stopBurst();
if(left != -1) {
- opt_response_content += anna::functions::entriesAsString(left, "message");
- opt_response_content += " left to the end of the cycle";
+ opt_response += anna::functions::entriesAsString(left, "message");
+ opt_response += " left to the end of the cycle";
}
} else if(param1 == "repeat") {
if(param2 == "") param2 = "yes";
bool repeat = (param2 == "yes");
getOperatedHost()->repeatBurst(repeat);
- opt_response_content += (repeat ? "repeat enabled" : "repeat disabled");
+ opt_response += (repeat ? "repeat enabled" : "repeat disabled");
} else if(param1 == "send") {
if(param2 == "") throw anna::RuntimeException("Missing amount for burst send operation", ANNA_FILE_LOCATION);
int sent = getOperatedHost()->sendBurst(atoi(param2.c_str()));
if(sent > 0) {
- opt_response_content = "sent ";
- opt_response_content += anna::functions::entriesAsString(sent, "message");
+ opt_response = "sent ";
+ opt_response += anna::functions::entriesAsString(sent, "message");
}
} else if(param1 == "goto") {
if(param2 == "") throw anna::RuntimeException("Missing order position for burst goto operation", ANNA_FILE_LOCATION);
- opt_response_content = getOperatedHost()->gotoBurst(atoi(param2.c_str()));
+ opt_response = getOperatedHost()->gotoBurst(atoi(param2.c_str()));
} else if(param1 == "look") {
int order = ((param2 != "") ? atoi(param2.c_str()) : -1);
- opt_response_content = "\n\n";
- opt_response_content += getOperatedHost()->lookBurst(order);
+ opt_response = "\n\n";
+ opt_response += getOperatedHost()->lookBurst(order);
} else {
throw anna::RuntimeException("Wrong body content format on HTTP Request for 'burst' operation (unexpected action parameter). Check 'HELP.md' for more information.", ANNA_FILE_LOCATION);
}
// Enables/disables report generation for a certain test case state: initialized, in-progress ...
// test|report-hex[|[yes]|no] Reports could include the diameter messages in hexadecimal format. Disabled by default.
// test|goto|<id> Updates current test pointer position.
+ // test|run|<id> Executes the given test case
// test|look[|id] Show programmed test case for id provided, current when missing ...
// test|state[|id] Show test case state for id provided, current when missing ...
// test|interact|amount|id Makes interactive a specific test case id. The amount is the margin of execution steps ...
bool success = ((param2 != "") ? testManager.configureTTPS(atoi(param2.c_str())) : false);
if (success) {
- opt_response_content = "assigned new test launch rate to ";
- opt_response_content += anna::functions::asString(atoi(param2.c_str()));
- opt_response_content += " events per second";
+ opt_response = "assigned new test launch rate to ";
+ opt_response += anna::functions::asString(atoi(param2.c_str()));
+ opt_response += " events per second";
}
else {
- opt_response_content += "unable to configure the test rate provided";
+ opt_response += "unable to configure the test rate provided";
}
}
else if (param1 == "next") {
bool success = testManager.execTestCases(sync_amount);
- opt_response_content = (success ? "" : "not completely " /* completed cycle and no repeats, rare case */);
- opt_response_content += "processed ";
- opt_response_content += anna::functions::asString(sync_amount);
- opt_response_content += ((sync_amount > 1) ? " test cases synchronously" : " test case");
+ opt_response = (success ? "" : "not completely " /* completed cycle and no repeats, rare case */);
+ opt_response += "processed ";
+ opt_response += anna::functions::asString(sync_amount);
+ opt_response += ((sync_amount > 1) ? " test cases synchronously" : " test case");
}
else if(param1 == "ip-limit") {
if (numParams > 2)
if (param2 != "") {
limit = atoi(param2.c_str());
testManager.setInProgressLimit(limit);
- opt_response_content = "new in-progress limit: ";
- opt_response_content += (limit != UINT_MAX) ? anna::functions::asString(limit) : "<no limit>";
+ opt_response = "new in-progress limit: ";
+ opt_response += (limit != UINT_MAX) ? anna::functions::asString(limit) : "[no limit]";
}
else {
- opt_response_content = "in-progress limit amount: ";
+ opt_response = "in-progress limit amount: ";
limit = testManager.getInProgressLimit();
- opt_response_content += (limit != UINT_MAX) ? anna::functions::asString(limit) : "<no limit>";
- opt_response_content += "; currently there are ";
- opt_response_content += anna::functions::asString(testManager.getInProgressCount());
- opt_response_content += " test cases running";
+ opt_response += (limit != UINT_MAX) ? anna::functions::asString(limit) : "[no limit]";
+ opt_response += "; currently there are ";
+ opt_response += anna::functions::asString(testManager.getInProgressCount());
+ opt_response += " test cases running";
}
}
else if(param1 == "repeats") {
if (repeats < 0) repeats = -1;
testManager.setPoolRepeats(repeats);
std::string nolimit = (repeats != -1) ? "":" [no limit]";
- opt_response_content += anna::functions::asString("Pool repeats: %d%s (current cycle: %d)", repeats, nolimit.c_str(), testManager.getPoolCycle());
+ opt_response += anna::functions::asString("Pool repeats: %d%s (current cycle: %d)", repeats, nolimit.c_str(), testManager.getPoolCycle());
}
else if(param1 == "report") {
if (numParams > 3)
else
throw anna::RuntimeException("Wrong body content format on HTTP Request. Check 'HELP.md' for more information.", ANNA_FILE_LOCATION);
- opt_response_content += (enable ? "report enabled " : "report disabled ");
- opt_response_content += "for tests in '";
- opt_response_content += param2;
- opt_response_content += "' state";
+ opt_response += (enable ? "report enabled " : "report disabled ");
+ opt_response += "for tests in '";
+ opt_response += param2;
+ opt_response += "' state";
}
else if(param1 == "report-hex") {
if (numParams > 2)
if(param2 == "") param2 = "yes";
testManager.setDumpHex((param2 == "yes"));
- opt_response_content += (testManager.getDumpHex() ? "report includes hexadecimal messages" : "report excludes hexadecimal messages");
+ opt_response += (testManager.getDumpHex() ? "report includes hexadecimal messages" : "report excludes hexadecimal messages");
}
else if(param1 == "dump-stdout") {
if (numParams > 2)
if(param2 == "") param2 = "yes";
testManager.setDumpStdout((param2 == "yes"));
- opt_response_content += (testManager.getDumpHex() ? "test manager dumps progress into stdout" : "test manager does not dump progress into stdout");
+ opt_response += (testManager.getDumpHex() ? "test manager dumps progress into stdout" : "test manager does not dump progress into stdout");
}
else if(param1 == "goto") {
if (numParams > 2)
if(param2 == "") throw anna::RuntimeException("Missing id for test goto operation", ANNA_FILE_LOCATION);
int id = atoi(param2.c_str());
if (testManager.gotoTestCase(id)) {
- opt_response_content = "position updated for id provided (";
+ opt_response = "position updated for id provided (";
}
else {
- opt_response_content = "cannot found test id (";
+ opt_response = "cannot found test id (";
}
- opt_response_content += anna::functions::asString(id);
- opt_response_content += ")";
+ opt_response += anna::functions::asString(id);
+ opt_response += ")";
}
else if(param1 == "run") {
if (numParams > 2)
if(param2 == "") throw anna::RuntimeException("Missing id for test run operation", ANNA_FILE_LOCATION);
int id = atoi(param2.c_str());
if (testManager.runTestCase(id)) {
- opt_response_content = "test executed for id provided (";
+ opt_response = "test executed for id provided (";
}
else {
- opt_response_content = "cannot found test id (";
+ opt_response = "cannot found test id (";
}
- opt_response_content += anna::functions::asString(id);
- opt_response_content += ")";
+ opt_response += anna::functions::asString(id);
+ opt_response += ")";
}
else if(param1 == "look") {
if (numParams > 2)
anna::testing::TestCase *testCase = testManager.findTestCase(id);
if (testCase) {
- response_content = testCase->asXMLString();
+ response = testCase->asXMLString();
return true; // OK
}
else {
result = false;
if (id == -1) {
- opt_response_content = "no current test case detected (testing started ?)";
+ opt_response = "no current test case detected (testing started ?)";
}
else {
- opt_response_content = "cannot found test id (";
- opt_response_content += anna::functions::asString(id);
- opt_response_content += ")";
+ opt_response = "cannot found test id (";
+ opt_response += anna::functions::asString(id);
+ opt_response += ")";
}
}
}
anna::testing::TestCase *testCase = testManager.findTestCase(id);
if (testCase) {
- response_content = anna::testing::TestCase::asText(testCase->getState());
+ response = anna::testing::TestCase::asText(testCase->getState());
return testCase->isSuccess();
}
else {
result = false;
if (id == -1) {
- opt_response_content = "no current test case detected (testing started ?)";
+ opt_response = "no current test case detected (testing started ?)";
}
else {
- opt_response_content = "cannot found test id (";
- opt_response_content += anna::functions::asString(id);
- opt_response_content += ")";
+ opt_response = "cannot found test id (";
+ opt_response += anna::functions::asString(id);
+ opt_response += ")";
}
}
}
if (testCase) {
if (amount == -1) {
testCase->makeInteractive(false);
- opt_response_content = "interactive mode disabled";
+ opt_response = "interactive mode disabled";
}
else {
testCase->addInteractiveAmount(amount);
- opt_response_content = "added interactive amount of ";
- opt_response_content += anna::functions::asString(amount);
- opt_response_content += " units";
- if (amount == 0) opt_response_content += " (0: freezing a non-interactive testcase, no effect on already interactive)";
+ opt_response = "added interactive amount of ";
+ opt_response += anna::functions::asString(amount);
+ opt_response += " units";
+ if (amount == 0) opt_response += " (0: freezing a non-interactive testcase, no effect on already interactive)";
}
- opt_response_content += " for test case id ";
- opt_response_content += anna::functions::asString(id);
+ opt_response += " for test case id ";
+ opt_response += anna::functions::asString(id);
}
else {
result = false;
- opt_response_content = "cannot found test id (";
- opt_response_content += anna::functions::asString(id);
- opt_response_content += ")";
+ opt_response = "cannot found test id (";
+ opt_response += anna::functions::asString(id);
+ opt_response += ")";
}
}
else if(param1 == "reset") {
if (testCase) {
bool done = testCase->reset(param2 == "hard");
- opt_response_content = "test ";
- opt_response_content += param2;
- opt_response_content += " reset for id ";
- opt_response_content += anna::functions::asString(id);
- opt_response_content += done ? ": done": ": not done";
+ opt_response = "test ";
+ opt_response += param2;
+ opt_response += " reset for id ";
+ opt_response += anna::functions::asString(id);
+ opt_response += done ? ": done": ": not done";
}
else {
if (id == -1) {
bool anyReset = testManager.resetPool(param2 == "hard");
- opt_response_content = param2; opt_response_content += " reset have been sent to all programmed tests: "; opt_response_content += anyReset ? "some/all have been reset" : "nothing was reset";
+ opt_response = param2; opt_response += " reset have been sent to all programmed tests: "; opt_response += anyReset ? "some/all have been reset" : "nothing was reset";
}
else {
result = false;
- opt_response_content = "cannot found test id (";
- opt_response_content += anna::functions::asString(id);
- opt_response_content += ")";
+ opt_response = "cannot found test id (";
+ opt_response += anna::functions::asString(id);
+ opt_response += ")";
}
}
}
throw anna::RuntimeException("Wrong body content format on HTTP Request. Check 'HELP.md' for more information.", ANNA_FILE_LOCATION);
testManager.setAutoResetHard(param2 == "hard");
- opt_response_content += anna::functions::asString("Auto-reset configured to '%s'", param2.c_str());
+ opt_response += anna::functions::asString("Auto-reset configured to '%s'", param2.c_str());
}
else if(param1 == "initialized") {
if (numParams > 1)
throw anna::RuntimeException("Wrong body content format on HTTP Request. Check 'HELP.md' for more information.", ANNA_FILE_LOCATION);
- opt_response_content = anna::functions::asString("%lu", testManager.getInitializedCount());
+ opt_response = anna::functions::asString("%lu", testManager.getInitializedCount());
}
else if(param1 == "finished") {
if (numParams > 1)
throw anna::RuntimeException("Wrong body content format on HTTP Request. Check 'HELP.md' for more information.", ANNA_FILE_LOCATION);
- opt_response_content = anna::functions::asString("%lu", testManager.getFinishedCount());
+ opt_response = anna::functions::asString("%lu", testManager.getFinishedCount());
}
else if(param1 == "clear") {
if (numParams > 1)
throw anna::RuntimeException("Wrong body content format on HTTP Request. Check 'HELP.md' for more information.", ANNA_FILE_LOCATION);
- if (testManager.clearPool()) {
- opt_response_content = "all the programmed test cases have been dropped";
- }
- else {
- opt_response_content = "there are not programmed test cases to be removed";
- }
+ result = testManager.clearPool(opt_response);
}
else if(param1 == "junit") {
- response_content = testManager.junitAsXMLString();
+ response = testManager.junitAsXMLString();
return true; // OK
}
else if(param1 == "summary-counts") {
- response_content = testManager.summaryCounts();
+ response = testManager.summaryCounts();
return true; // OK
}
else if(param1 == "summary-states") {
- response_content = testManager.summaryStates();
+ response = testManager.summaryStates();
return true; // OK
}
else if(param1 == "summary") {
- response_content = testManager.asXMLString();
+ response = testManager.asXMLString();
return true; // OK
}
else {
}
}
- } else if((opType == "sendxml2c") || (opType == "sendhex2c")) {
- anna::diameter::comm::Message *msg;
-
- if(opType == "sendxml2c") {
- codecMsg.loadXMLFile(param1);
- updateOperatedOriginHostWithMessage(codecMsg);
- msg = getOperatedHost()->createCommMessage();
- msg->clearBody();
- try { 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)
-
- msg->setBody(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);
- msg = getOperatedHost()->createCommMessage();
- msg->setBody(db_aux);
- }
-
- bool success = getOperatedServer()->send(msg);
- getOperatedHost()->releaseCommMessage(msg);
-
- // Detailed log:
- if(getOperatedHost()->logEnabled()) {
- anna::diameter::comm::ServerSession *usedServerSession = getOperatedServer()->getLastUsedResource();
- std::string detail = usedServerSession ? usedServerSession->asString() : "<null server session>"; // shouldn't happen
- getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2c" : "send2cError"), detail);
- }
} else if(opType == "loadxml") {
codecMsg.loadXMLFile(param1);
- response_content = codecMsg.asXMLString();
+ response = codecMsg.asXMLString();
return true; // OK
} else if(opType == "diameterServerSessions") {
int diameterServerSessions = atoi(param1.c_str());
getOperatedServer()->setMaxConnections(diameterServerSessions);
- } else if(opType == "answerxml2c") {
- if(param1 == "") { // programmed answers FIFO's to stdout
- response_content = getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT");
- return true; // OK
- } else if (param1 == "rotate") {
- getOperatedServer()->getReactingAnswers()->rotate(true);
- } else if (param1 == "exhaust") {
- getOperatedServer()->getReactingAnswers()->rotate(false);
- } else if (param1 == "clear") {
- getOperatedServer()->getReactingAnswers()->clear();
- } else if (param1 == "dump") {
- getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
- } else {
- codecMsg.loadXMLFile(param1);
- updateOperatedOriginHostWithMessage(codecMsg);
- anna::diameter::codec::Message *message = getOperatedHost()->getCodecEngine()->createMessage(param1); // loads xml again, lesser of two evils
- LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
- if(message->isRequest())
- throw anna::RuntimeException("Cannot program diameter requests. Answer type must be provided", ANNA_FILE_LOCATION);
- int code = message->getId().first;
- LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to client' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
- getOperatedServer()->getReactingAnswers()->addMessage(code, message);
- }
- } else if(opType == "answerxml2e") {
-
- if(param1 == "") { // programmed answers FIFO's to stdout
- response_content = getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY");
- return true; // OK
- } else if (param1 == "rotate") {
- getOperatedEntity()->getReactingAnswers()->rotate(true);
- } else if (param1 == "exhaust") {
- getOperatedEntity()->getReactingAnswers()->rotate(false);
- } else if (param1 == "clear") {
- getOperatedEntity()->getReactingAnswers()->clear();
- } else if (param1 == "dump") {
- getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
- } else {
- codecMsg.loadXMLFile(param1);
- updateOperatedOriginHostWithMessage(codecMsg);
- anna::diameter::codec::Message *message = getOperatedHost()->getCodecEngine()->createMessage(param1); // loads xml again, lesser of two evils
- LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
-
- if(message->isRequest())
- throw anna::RuntimeException("Cannot program diameter requests. Answer type must be provided", ANNA_FILE_LOCATION);
-
- int code = message->getId().first;
- LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to entity' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
- getOperatedEntity()->getReactingAnswers()->addMessage(code, message);
- }
} else {
throw anna::RuntimeException("Wrong body content format on HTTP Request. Check 'HELP.md' for more information.", ANNA_FILE_LOCATION);
}
+
+
// HTTP response
- response_content = "Operation correctly processed: "; response_content += operation;
- if (opt_response_content != "") {
- response_content += " => ";
- response_content += opt_response_content;
+ response = "Operation correctly processed: "; response += operation;
+ if (opt_response != "") {
+ response += " => ";
+ response += opt_response;
}
return result;