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 += "\nIf a request is received, answer map (built with 'answerxml<[2c] or 2e>' operations) will be";
+ result += "\nSame 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 += "\nanswerhex2e|[source_file] Answer hex source file (pathfile) for corresponding request from entity.";
+ result += "\nanswerhex2c|[source_file] Answer hex source file (pathfile) for corresponding request from client.";
+ result += "\nanswerhex|[source_file] Same as 'answerhex2c'.";
+ result += "\n List programmed answers if no parameter provided.";
+ result += "\n";
+ result += "\n";
+ result += "\n";
+ result += "\nIf a request is received, answer map (built with 'answerxml/hex<[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 or nothing but trace when no peer at that side is configured. Answer to client have sense when";
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";
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("Cannot interpret hexadecimal content from 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("Cannot interpret hexadecimal content from 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("Cannot interpret hexadecimal content from 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 += "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.";
- <command name="AA-Request" code="265" type="Request">
- <avprule id="Session-Id" type="Fixed"/>
- <avprule id="Auth-Application-Id" type="Mandatory"/>
- <avprule id="Origin-Host" type="Mandatory"/>
- <avprule id="Origin-Realm" type="Mandatory"/>
- <avprule id="Destination-Realm" type="Mandatory"/>
- <avprule id="Destination-Host" type="Optional"/>
- <avprule id="AF-Application-Identifier" type="Optional"/>
- <avprule id="Media-Component-Description" type="Optional" qual="*"/>
- <avprule id="Service-Info-Status" type="Optional"/>
- <avprule id="AF-Charging-Identifier" type="Optional"/>
- <avprule id="SIP-Forking-Indication" type="Optional"/>
- <avprule id="Specific-Action" type="Optional" qual="*"/>
- <avprule id="Subscription-Id" type="Optional" qual="*"/>
- <avprule id="Supported-Features" type="Optional" qual="*"/>
- <avprule id="Reservation-Priority" type="Optional"/>
- <avprule id="Framed-IP-Address" type="Optional"/>
- <avprule id="Framed-IPv6-Prefix" type="Optional"/>
- <avprule id="Called-Station-Id" type="Optional"/>
- <avprule id="Service-URN" type="Optional"/>
- <avprule id="Sponsored-Connectivity-Data" type="Optional"/>
- <avprule id="MPS-Identifier" type="Optional"/>
- <avprule id="Rx-Request-Type" type="Optional"/>
- <avprule id="Origin-State-Id" type="Optional"/>
- <avprule id="Proxy-Info" type="Optional" qual="*"/>
- <avprule id="Route-Record" type="Optional" qual="*"/>
- <avprule id="AVP" type="Optional" qual="*"/>
- </command>
-
-<message version="1" name="Credit-Control-Request" p-bit="yes" application-id="4" hop-by-hop-id="1" end-by-end-id="1">
- <avp name="Session-Id" data="module-2.PTS2-BOG.sandvine.com;1287115741;0;0"/>
- <avp name="Origin-Host" data="module-2.PTS2-BOG.sandvine.com"/>
- <avp name="Origin-Realm" data="sandvine.com"/>
- <avp name="Destination-Realm" data="telefonica.com.co"/>
- <avp name="Auth-Application-Id" data="4"/>
- <avp name="Service-Context-Id" data="770.32251@3gpp.org"/>
- <avp name="CC-Request-Type" data="1" alias="INITIAL_REQUEST"/>
- <avp name="CC-Request-Number" data="0"/>
- <avp name="User-Name" data="50583211675"/>
- <avp name="Origin-State-Id" data="1339077627"/>
- <avp name="Event-Timestamp" data="3548171033"/>
+<message version="1" name="AA-Request" p-bit="yes" application-id="16777236" hop-by-hop-id="0" end-by-end-id="0">
+ <avp name="Session-Id" data="ocs3;1332774430;1;1332774430"/>
+ <avp name="Auth-Application-Id" data="16777236"/>
+ <avp name="Origin-Host" data="OCS3"/>
+ <avp name="Origin-Realm" data="OCS3"/>
+ <avp name="Destination-Realm" data="OCS3"/>
+ <avp name="Destination-Host" data="OCS3"/>
+ <avp name="AF-Application-Identifier" hex-data="313232"/>
+ <avp name="Media-Component-Description">
+ <avp name="Media-Component-Number" data="0"/>
+ <avp name="AF-Application-Identifier" hex-data="313232"/>
+ <avp name="Max-Requested-Bandwidth-UL" data="127"/>
+ <avp name="Max-Requested-Bandwidth-DL" data="133"/>
+ <avp name="Flow-Status" data="2" alias="ENABLED"/>
+ <avp name="Reservation-Priority" data="0" alias="DEFAULT"/>
+ </avp>
+ <avp name="Service-Info-Status" data="0" alias="FINAL_SERVICE_INFORMATION"/>
<avp name="Subscription-Id">
<avp name="Subscription-Id-Type" data="0" alias="END_USER_E164"/>
- <avp name="Subscription-Id-Data" data="50583211675"/>
- </avp>
- <avp name="Multiple-Services-Indicator" data="1" alias="MULTIPLE_SERVICES_SUPPORTED"/>
- <avp name="User-Equipment-Info">
- <avp name="User-Equipment-Info-Type" data="0" alias="IMEISV"/>
- <avp name="User-Equipment-Info-Value" hex-data="33353430343630343130363438333030"/>
- </avp>
- <avp name="Service-Information">
- <avp name="PS-Information">
- <avp name="3GPP-Charging-Id" data="29"/>
- <avp name="3GPP-PDP-Type" data="0" alias="IPV4"/>
- <avp name="PDP-Address" data="10.193.49.133"/>
- <avp name="3GPP-GPRS-Neg-QoS-Profile" data="05-1b921f7196fefe74fbfefe00"/>
- <avp name="SGSN-Address" data="190.98.183.240"/>
- <avp name="GGSN-Address" data="190.98.183.243"/>
- <avp name="CG-Address" data="10.193.249.1"/>
- <avp name="3GPP-IMSI-MCC-MNC" data="71204"/>
- <avp name="3GPP-GGSN-MCC-MNC" data="71204"/>
- <avp name="3GPP-NSAPI" data="5"/>
- <avp name="Called-Station-Id" data="internet.movistar.ni"/>
- <avp name="3GPP-Selection-Mode" data="0"/>
- <avp name="3GPP-Charging-Characteristics" data="0800"/>
- <avp name="3GPP-SGSN-MCC-MNC" data="33403"/>
- <avp name="3GPP-MS-TimeZone" hex-data="4a00"/>
- <avp name="3GPP-User-Location-Info" hex-data="0117f240a4780218"/>
- <avp name="3GPP-Rat-Type" hex-data="01"/>
- <avp name="PDP-Context-Type" data="0"/>
- </avp>
+ <avp name="Subscription-Id-Data" data="626037099"/>
</avp>
+ <avp name="Framed-IP-Address" hex-data="3139322e3136382e302e31"/>
+ <avp name="Called-Station-Id" data="WAP.MOVISTAR"/>
</message>