X-Git-Url: https://git.teslayout.com/public/public/public/?p=anna.git;a=blobdiff_plain;f=example%2Fdiameter%2Flauncher%2FMyHandler.cpp;h=ed49f4f125c8ba1f86b2e164a2c05e00e59e133a;hp=6638fc37985cd2587ccda64f2357f75c2aa6b85e;hb=c881c12ed7e116f1d43760a0d9873f860c10a357;hpb=af14877201a9856708ec43086a229777d9cb3da7 diff --git a/example/diameter/launcher/MyHandler.cpp b/example/diameter/launcher/MyHandler.cpp index 6638fc3..ed49f4f 100644 --- a/example/diameter/launcher/MyHandler.cpp +++ b/example/diameter/launcher/MyHandler.cpp @@ -10,74 +10,551 @@ #include #include #include +#include // Project #include +#include // Process #include #include #include +void MyHandler::splitURI(const std::string &uri, std::string & operation, std::string & param1, std::string & param2) const { + + std::string::size_type slash_pos = uri.find("/", 1u); + if (slash_pos == std::string::npos) { + operation = uri.substr(0); + } + else { + operation = uri.substr(0, slash_pos); + param1 = uri.substr(slash_pos + 1); + + std::string::size_type slash2_pos = uri.find("/", slash_pos + 1); + if (slash2_pos != std::string::npos) { + param1 = uri.substr(slash_pos + 1, slash2_pos - slash_pos - 1); + param2 = uri.substr(slash2_pos + 1); + } + } +} + +void MyHandler::sendResponse(anna::comm::ClientSocket& clientSocket, anna::http::Response *response) +{ + try { + clientSocket.send(*response); + } catch(Exception& ex) { + ex.trace(); + } +} void MyHandler::evRequest(anna::comm::ClientSocket& clientSocket, const anna::http::Request& request) throw(anna::RuntimeException) { - const anna::DataBlock& body = request.getBody(); - - if(body.getSize() == 0) - throw anna::RuntimeException("Missing operation parameters on HTTP request", ANNA_FILE_LOCATION); - LOGINFORMATION( - std::string msg("Received body: "); - msg += anna::functions::asString(body); - anna::Logger::information(msg, ANNA_FILE_LOCATION); - ); + const anna::DataBlock& body = request.getBody(); + anna::http::Method::Type::_v method = request.getMethod(); + std::string uri = request.getURI(); + bool isGET = (method == anna::http::Method::Type::Get); + bool isPOST = (method == anna::http::Method::Type::Post); std::string body_content; - body_content.assign(body.getData(), body.getSize()); - auto json_body = nlohmann::json::parse(body_content); + nlohmann::json json_body; + std::stringstream ss; - // Operation: - std::string response_content; + anna::http::Response* response = allocateResponse(); + response->setStatusCode(200); - bool opOk{}; + if (isGET) { + if(body.getSize() != 0) + response->setStatusCode(400); // bad request + } + else if (isPOST) { + if(body.getSize() != 0) { + body_content.assign(body.getData(), body.getSize()); // assign body content: - try { - Launcher& my_app = static_cast (anna::app::functions::getApp()); - opOk = my_app.eventOperation(EventOperation::json2piped(json_body), response_content); - } catch(RuntimeException &ex) { - ex.trace(); - opOk = false; + try { + json_body = nlohmann::json::parse(body_content); + LOGINFORMATION( + std::string msg("Json body received:\n\n"); + msg += json_body.dump(4); // pretty print json body + anna::Logger::information(msg, ANNA_FILE_LOCATION); + ); + } + catch (nlohmann::json::parse_error& e) + { + ss << "Json body parse error: " << e.what() << '\n' + << "exception id: " << e.id << '\n' + << "byte position of error: " << e.byte << std::endl; + anna::Logger::error(ss.str(), ANNA_FILE_LOCATION); + } + } + } + else { + response->setStatusCode(405); // method not allowed } - anna::http::Response* response = allocateResponse(); - response->setStatusCode(200); // http://en.wikipedia.org/wiki/List_of_HTTP_status_codes - -// EXAMPLES TO SET HEADERS: -// response->find(anna::http::Header::Type::Date)->setValue("Mon, 30 Jan 2006 14:36:18 GMT"); -// anna::http::Header* keepAlive = response->find("Keep-Alive"); -// -// if (keepAlive == NULL) -// keepAlive = response->createHeader("Keep-Alive"); -// -// keepAlive->setValue("Verificacion del cambio 1.0.7"); - - // Content-Type header: - anna::http::Header* contentType = response->find("Content-Type"); - if (contentType == NULL) - contentType = response->createHeader("Content-Type"); + ////////////////////// + // Prepare response // + ////////////////////// + + // Headers: + http::Header* contentType =response->find(http::Header::Type::ContentType); + if(contentType == NULL) + contentType = response->createHeader(http::Header::Type::ContentType); contentType->setValue("application/json"); - // Json Body for response: - std::stringstream ss; + // Body: + std::string response_content = "Internal error (check ADML traces): "; + bool success = false; + if (isGET) { + success = doGET(uri, response_content); + } + else if (isPOST) { + try { + success = doPOST(uri, json_body, response_content); + } + catch(anna::RuntimeException &ex) { + ex.trace(); + LOGINFORMATION(anna::Logger::information("XXXXXXXXXXXX EXCEPCION PENDIENTE DE CATCHEAR ABAJO !!! XXXXXXXXXXXXXXXXX", ANNA_FILE_LOCATION)); + } + } + + ss << R"({ "success":")" << (success ? "true":"false") + << R"(", "response": )" << std::quoted(response_content); + ss << R"( })"; - ss << R"({ "result":")" << (opOk ? "true":"false") << R"(", "data": )" << std::quoted(response_content) << R"( })"; anna::DataBlock db_content(true); db_content = ss.str(); response->setBody(db_content); - try { - clientSocket.send(*response); - } catch(Exception& ex) { - ex.trace(); + sendResponse(clientSocket, response); +} + +bool MyHandler::doGET(const std::string &uri, std::string &response) { + + bool result = false; + + EventOperation eop(true /* is HTTP */); + + // Snapshots + if (uri == "/show-oam") { + result = eop.show_oam(response); + } + else if (uri == "/show-stats") { + result = eop.show_stats(response); + } + + return result; +} + +bool MyHandler::doPOST(const std::string &uri, const nlohmann::json &j, std::string &response) { + + bool result = false; + + EventOperation eop(true /* is HTTP */); + + std::string opType{}, param1{}, param2{}; + splitURI(uri, opType, param1, param2); + + // Node management + if (opType == "/node") { + auto it = j.find("name"); + if (it != j.end()) + result = eop.node(response, *it); + else + response += "missing 'name' string field"; + } + else if (opType == "/node-auto") { + result = eop.node_auto(response); + } + + // Parsing operations + else if (opType == "/code") { + auto it = j.find("diameterJson"); + if (it != j.end()) + result = eop.code(response, it->dump(4)); // get the object as string (always indentation = 4) + else + response += "missing 'diameterJson' object field"; + } + else if (opType == "/decode") { + auto it = j.find("diameterHex"); + if (it != j.end()) + result = eop.decode(response, *it); + else + response += "missing 'diameterHex' string field"; + } + else if (opType == "/loadmsg") { + auto it = j.find("diameterJson"); + if (it != j.end()) + result = eop.loadmsg(response, it->dump(4)); // get the object as string (always indentation = 4) + else + response += "missing 'diameterJson' object field"; + } + + // Hot changes + else if (opType == "/services") { + auto it = j.find("servicesJson"); + if (it != j.end()) { + result = eop.services(response, it->dump(4)); // get the object as string (always indentation = 4) + } + else + response += "missing 'servicesJson' object field"; + } + else if (opType == "/diameterServerSessions") { + auto it = j.find("sessions"); + if (it != j.end()) + result = eop.diameterServerSessions(response, it->get()); + else + response += "missing 'session' integer field"; + } + else if (opType == "/change-dir") { + auto it = j.find("directory"); + std::string directory = (it != j.end()) ? *it : ""; // default is: restore initial directory + result = eop.change_dir(response, directory); + } + + // Client sessions visibility + else if (opType == "/visibility") { + auto it = j.find("action"); + if (it != j.end()) { + std::string action = *it; + + it = j.find("addressPort"); + std::string addressPort = (it != j.end()) ? *it : ""; + + it = j.find("socket"); + int socket = (it != j.end()) ? it->get() : -1; + + result = eop.visibility(response, action, addressPort, socket); + } + else + response += "missing 'action' string field"; + } + + // Snapshots + else if (opType == "/collect") { + result = eop.collect(response); } + else if (opType == "/context") { + auto it = j.find("targetFile"); + std::string targetFile = (it != j.end()) ? *it : ""; + result = eop.context(response, targetFile); + } + else if (opType == "/forceCountersRecord") { + result = eop.forceCountersRecord(response); + } + else if (opType == "/log-statistics-samples") { + auto it = j.find("list"); + if (it != j.end()) + result = eop.log_statistics_samples(response, *it); + else + response += "missing 'list' string field"; + } + + // Flow operations + else if ((opType == "/sendmsg2e")||(opType == "/sendmsg2c")) { + auto it = j.find("diameterJson"); + if (it != j.end()) + if (opType == "/sendmsg2e") + result = eop.sendmsg2e(response, it->dump(4)); // get the object as string (always indentation = 4) + else + result = eop.sendmsg2c(response, it->dump(4)); // get the object as string (always indentation = 4) + else + response += "missing 'diameterJson' object field"; + } + else if ((opType == "/answermsg2e")||(opType == "/answermsg2c")) { + auto itJ = j.find("diameterJson"); + auto itA = j.find("action"); + bool hasJ = (itJ != j.end()); + bool hasA = (itA != j.end()); + + if (hasJ != hasA) { // XOR + + if (opType == "/answermsg2e") { + if (hasJ) + result = eop.answermsg2e(response, itJ->dump(4)); // get the object as string (always indentation = 4) + else + result = eop.answermsg2e_action(response, *itA); + } + else { + if (hasJ) + result = eop.answermsg2c(response, itJ->dump(4)); // get the object as string (always indentation = 4) + else + result = eop.answermsg2c_action(response, *itA); + } + } + else + response += "missing 'diameterJson' object or 'action' string field (only one accepted)"; + } + else if ((opType == "/sendhex2e")||(opType == "/sendhex2c")) { + auto it = j.find("diameterHex"); + if (it != j.end()) + if (opType == "/sendhex2e") + result = eop.sendhex2e(response, *it); + else + result = eop.sendhex2c(response, *it); + else + response += "missing 'diameterHex' string field"; + } + + // FSM testing + // test_id__ + else if (opType == "/testid-description") { + auto it = j.find("description"); + if (it != j.end()) + result = eop.test_id__description(response, atoi(param1.c_str()), *it); + else + response += "missing 'description' string field"; + } + else if (opType == "/testid-ip-limit") { + auto it = j.find("amount"); + int amount = (it != j.end()) ? it->get() : 1; + result = eop.test_id__ip_limit(response, atoi(param1.c_str()), amount); + } + else if (opType == "/testid-timeout") { + auto it = j.find("msecs"); + if (it != j.end()) + result = eop.test_id__timeout(response, atoi(param1.c_str()), it->get()); + else + response += "missing 'msecs' integer field"; + } + else if ((opType == "/testid-sendmsg2e")||(opType == "/testid-sendmsg2c")) { + auto it = j.find("diameterJson"); + if (it != j.end()) { + + auto itS = j.find("stepNumber"); + int stepNumber = (itS != j.end()) ? itS->get() : -1; + + if (opType == "/testid-sendmsg2e") + result = eop.test_id__sendmsg2e(response, atoi(param1.c_str()), it->dump(4), stepNumber); // get the object as string (always indentation = 4) + else + result = eop.test_id__sendmsg2c(response, atoi(param1.c_str()), it->dump(4), stepNumber); // get the object as string (always indentation = 4) + } + else + response += "missing 'diameterJson' object field"; + } + else if (opType == "/testid-delay") { + auto it = j.find("msecs"); + if (it != j.end()) + result = eop.test_id__delay(response, atoi(param1.c_str()), it->get()); + else + response += "missing 'msecs' integer field"; + } + else if (opType == "/testid-sh-command") { + auto it = j.find("script"); + if (it != j.end()) + result = eop.test_id__sh_command(response, atoi(param1.c_str()), *it); + else + response += "missing 'script' string field"; + } + else if ((opType == "/testid-waitfe-hex")||(opType == "/testid-waitfc-hex")) { + auto it = j.find("hex"); + if (it != j.end()) { + + auto itS = j.find("strict"); + bool strict = (itS != j.end()) ? (*itS == "true") : false; + + if (opType == "/testid-waitfe-hex") + result = eop.test_id__waitfe_hex(response, atoi(param1.c_str()), *it, strict); + else + result = eop.test_id__waitfc_hex(response, atoi(param1.c_str()), *it, strict); + } + else + response += "missing 'hex' string field"; + } + else if ((opType == "/testid-waitfe-msg")||(opType == "/testid-waitfc-msg")) { + auto it = j.find("diameterJson"); + if (it != j.end()) { + + auto itS = j.find("strict"); + bool strict = (itS != j.end()) ? (*itS == "true") : false; + + if (opType == "/testid-waitfe-msg") + result = eop.test_id__waitfe_msg(response, atoi(param1.c_str()), it->dump(4), strict); // get the object as string (always indentation = 4) + else + result = eop.test_id__waitfc_msg(response, atoi(param1.c_str()), it->dump(4), strict); // get the object as string (always indentation = 4) + } + else + response += "missing 'diameterJson' object field"; + } + else if ((opType == "/testid-waitfe")||(opType == "/testid-waitfc")) { + auto it = j.find("condition"); + if (it != j.end()) { + // [code]|[bitR]|[hopByHop]|[applicationId]|[sessionId]|[resultCode]|[msisdn]|[imsi]|[serviceContextId] + auto it_code = it->find("code"); + auto it_bitR = it->find("bitR"); + auto it_hopByHop = it->find("hopByHop"); + auto it_applicationId = it->find("applicationId"); + auto it_sessionId = it->find("sessionId"); + auto it_resultCode = it->find("resultCode"); + auto it_msisdn = it->find("msisdn"); + auto it_imsi = it->find("imsi"); + auto it_serviceContextId = it->find("serviceContextId"); + + std::string condition; + condition += (it_code != it->end()) ? *it_code : ""; condition += "|"; + condition += (it_bitR != it->end()) ? *it_bitR : ""; condition += "|"; + condition += (it_hopByHop != it->end()) ? *it_hopByHop : ""; condition += "|"; + condition += (it_applicationId != it->end()) ? *it_applicationId : ""; condition += "|"; + condition += (it_sessionId != it->end()) ? *it_sessionId : ""; condition += "|"; + condition += (it_resultCode != it->end()) ? *it_resultCode : ""; condition += "|"; + condition += (it_msisdn != it->end()) ? *it_msisdn : ""; condition += "|"; + condition += (it_imsi != it->end()) ? *it_imsi : ""; condition += "|"; + condition += (it_serviceContextId != it->end()) ? *it_serviceContextId : ""; + + if (opType == "/testid-waitfe") + result = eop.test_id__waitfe(response, atoi(param1.c_str()), condition); + else + result = eop.test_id__waitfc(response, atoi(param1.c_str()), condition); + } + else + response += "missing 'condition' object field"; + } + + // Testcases execution + // test__ + else if (opType == "/test-ttps") { + auto it = j.find("amount"); + if (it != j.end()) + result = eop.test__ttps(response, it->get()); + else + response += "missing 'amount' integer field"; + } + else if (opType == "/test-next") { + auto it = j.find("syncAmount"); + int syncAmount = (it != j.end()) ? it->get() : 1; + result = eop.test__next(response, syncAmount); + } + else if (opType == "/test-ip-limit") { + auto it = j.find("amount"); + int amount = (it != j.end()) ? it->get() : -2; // default is: show current ip-limit and in-progress test cases amount + result = eop.test__ip_limit(response, amount); + } + else if (opType == "/test-goto") { + auto it = j.find("id"); + if (it != j.end()) + result = eop.test__goto(response, it->get()); + else + response += "missing 'id' integer field"; + } + else if (opType == "/test-run") { + auto it = j.find("id"); + if (it != j.end()) + result = eop.test__run(response, it->get()); + else + response += "missing 'id' integer field"; + } + else if (opType == "/test-look") { + auto it = j.find("id"); + int id = (it != j.end()) ? it->get() : -1; // default is: current + result = eop.test__look(response, id); + } + else if (opType == "/test-state") { + auto it = j.find("id"); + int id = (it != j.end()) ? it->get() : -1; // default is: current + result = eop.test__state(response, id); + } + else if (opType == "/test-interact") { + auto it = j.find("amount"); + if (it != j.end()) { + + auto itI = j.find("id"); + int id = (itI != j.end()) ? itI->get() : -1; // default is: current + + result = eop.test__interact(response, it->get(), id); + } + else + response += "missing 'amount' integer field"; + } + else if (opType == "/test-reset") { + auto it = j.find("type"); + if (it != j.end()) { + + auto itI = j.find("id"); + int id = (itI != j.end()) ? itI->get() : -2; // default is: apply to all the tests + + if ((*it == "soft") || (*it == "hard")) { + result = eop.test__reset(response, (*it == "soft"), id); + } + else + response += "invalid 'type' string field (allowed: soft|hard)"; + } + else + response += "missing 'type' string field"; + } + else if (opType == "/test-repeats") { + auto it = j.find("amount"); + if (it != j.end()) + result = eop.test__repeats(response, it->get()); + else + response += "missing 'amount' integer field"; + } + else if (opType == "/test-auto-reset") { + auto it = j.find("type"); + if (it != j.end()) { + + if ((*it == "soft") || (*it == "hard")) { + result = eop.test__auto_reset(response, (*it == "soft")); + } + else + response += "invalid 'type' string field (allowed: soft|hard)"; + } + else + response += "missing 'type' string field"; + } + else if (opType == "/test-initialized") { + result = eop.test__initialized(response); + } + else if (opType == "/test-finished") { + result = eop.test__finished(response); + } + else if (opType == "/test-clear") { + result = eop.test__clear(response); + } + else if (opType == "/test-junit") { + auto it = j.find("targetFile"); + std::string targetFile = (it != j.end()) ? *it : ""; // default is: get junit on response instead dumping on file + result = eop.test__junit(response, targetFile); + } + else if (opType == "/test-summary-counts") { + result = eop.test__summary_counts(response); + } + else if (opType == "/test-summary-states") { + result = eop.test__summary_states(response); + } + else if (opType == "/test-summary") { + result = eop.test__summary(response); + } + else if (opType == "/test-report") { + auto it = j.find("state"); + std::string state = (it != j.end()) ? *it : "all"; // initialized|in-progress|failed|success|[all]|none + + auto itA = j.find("action"); + std::string action = (itA != j.end()) ? *itA : "enable"; // default is: enable + + if ((action == "enable") || (action == "disable")) { + result = eop.test__report(response, state, (action == "enable")); + } + else + response += "invalid 'action' string field (allowed: enable|disable)"; + } + else if ((opType == "/test-report-hex")||(opType == "/test-dump_stdout")) { + + auto itA = j.find("action"); + std::string action = (itA != j.end()) ? *itA : "enable"; // default is: enable + + if ((action == "enable") || (action == "disable")) { + bool enable = (action == "enable"); + + if (opType == "/test-report-hex") + result = eop.test__report_hex(response, enable); + else + result = eop.test__dump_stdout(response, enable); + } + else + response += "invalid 'action' string field (allowed: enable|disable)"; + } + + + return result; } +