From: Eduardo Ramos Testillano Date: Sat, 4 Apr 2015 01:35:17 +0000 (+0200) Subject: pcapDecoder allows .hex files as input. Make public some Avp methods for serializatio... X-Git-Tag: REFACTORING_TESTING_LIBRARY~196 X-Git-Url: https://git.teslayout.com/public/public/public/?a=commitdiff_plain;h=e7dbacff41163bf8cefb267daae84d96056ebc86;p=anna.git pcapDecoder allows .hex files as input. Make public some Avp methods for serialization (decode, code, etc.). Gx and Sy app Ids in define.hpp. --- diff --git a/example/diameter/launcher/main.cpp b/example/diameter/launcher/main.cpp index 48b304d..7a08518 100644 --- a/example/diameter/launcher/main.cpp +++ b/example/diameter/launcher/main.cpp @@ -1512,7 +1512,7 @@ throw(anna::RuntimeException) { std::string buffer = d->asXMLString(); out.write(buffer.c_str(), buffer.size()); out.close(); - std::cout << "Written '" << all_in_one << "' (provide it next time to be more comfortable)." << std::endl; + std::cout << "Written accumulated '" << all_in_one << "' (provide it next time to be more comfortable)." << std::endl; } } catch (anna::RuntimeException &ex) { diff --git a/example/diameter/pcapDecoder/main.cpp b/example/diameter/pcapDecoder/main.cpp index 8e3e866..65681d8 100644 --- a/example/diameter/pcapDecoder/main.cpp +++ b/example/diameter/pcapDecoder/main.cpp @@ -289,6 +289,41 @@ void my_callback(u_char *useless, const struct pcap_pkthdr* pkthdr, count++; } +bool getDataBlockFromHexFile(const std::string &pathfile, anna::DataBlock &db) throw() { + + // Get hex string + static char buffer[8192]; + std::ifstream infile(pathfile.c_str(), std::ifstream::in); + if(infile.is_open()) { + infile >> buffer; + std::string hexString(buffer, strlen(buffer)); + // Allow colon separator in hex string: we have to remove them before processing with 'fromHexString': + hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end()); + LOGDEBUG( + std::string msg = "Hex string (remove colons if exists): "; + msg += hexString; + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); + + anna::functions::fromHexString(hexString, db); + // Close file + infile.close(); + return true; + } + + return false; +} + + +void _exit(const std::string &message, int resultCode = 1) { + if (resultCode) + std::cerr << message << std::endl << std::endl; + else + std::cout << message << std::endl << std::endl; + exit(resultCode); +} + + //------------------------------------------------------------------- int main(int argc, char **argv) { std::string exec = argv[0]; @@ -296,19 +331,22 @@ int main(int argc, char **argv) { //check command line arguments if(argc < 3) { - std::cout << "Usage: " << exec - << " [--ignore-flags: non-strict validation]" - << std::endl << std::endl; - return 1; + std::string msg = "Usage: "; msg += exec; + msg += " [--ignore-flags: non-strict validation]\n\n"; + msg += " dictionaries: list of comma-separated xml dictionaries (one or more can be provided).\n"; + msg += " Input file: normally a pcap file, but hexadecimal content (colons allowed) can also be decoded (use '.hex' extension)."; + _exit(msg); } // Command-line parameters: std::string dictionaries = argv[1]; - std::string pcapFile = argv[2]; + std::string inputFile = argv[2]; + bool isHex = (inputFile.substr(inputFile.find_last_of(".") + 1) == "hex"); + std::string outputFile = inputFile; // extension will be added later std::string optional = argv[3] ? argv[3] : ""; bool ignoreFlags = ((argc == 4) && (optional == "--ignore-flags")); std::cout << "Dictionary(ies) provided: " << dictionaries << std::endl; - std::cout << "Pcap file provided: " << pcapFile << std::endl; + std::cout << "Input file provided: " << inputFile << std::endl; std::cout << "Validation kindness: " << (ignoreFlags ? "non strict" : "strict") << std::endl; // Logger and engines: @@ -348,18 +386,45 @@ int main(int argc, char **argv) { std::string buffer = d->asXMLString(); out.write(buffer.c_str(), buffer.size()); out.close(); - std::cout << "Written '" << all_in_one + std::cout << "Written accumulated '" << all_in_one << "' (provide it next time to be more comfortable)." << std::endl; } } catch(anna::RuntimeException &ex) { - std::cerr << ex.asString() << std::endl << std::endl; - return 1; + _exit(ex.asString()); } codecEngine->ignoreFlagsOnValidation(ignoreFlags); // Tracing: //if (cl.exists("trace")) // anna::Logger::setLevel(anna::Logger::asLevel(cl.getValue("trace"))); + + // Check hex content input file (look extension): + anna::DataBlock db_aux(true); + if(isHex) { + if (!getDataBlockFromHexFile(inputFile, db_aux)) + _exit("Error reading hex file provided"); + + try { + G_codecMsg.decode(db_aux); + } catch(RuntimeException &ex) { + _exit(ex.asString()); + } + + // Open output file: + outputFile += ".as.xml"; + std::ofstream out(outputFile, std::ifstream::out); + out << G_codecMsg.asXMLString(); + + // Close output file: + out.close(); + + std::string msg = "Open 'file.trace' in order to see process traces.\n"; + msg += "Open '"; msg += outputFile; msg += "' to see decoding results."; + _exit(msg, 0); + } + + // Normal input: pcap file: + // SNIFFING //////////////////////////////////////////////////////////////////////////////////////////////7 //temporary packet buffers struct pcap_pkthdr header; // The header that pcap gives us @@ -368,12 +433,9 @@ int main(int argc, char **argv) { //open the pcap file pcap_t *handle; char errbuf[PCAP_ERRBUF_SIZE]; //not sure what to do with this, oh well - handle = pcap_open_offline(pcapFile.c_str(), errbuf); //call pcap library function + handle = pcap_open_offline(inputFile.c_str(), errbuf); //call pcap library function - if(handle == NULL) { - std::cerr << errbuf << std::endl << std::endl; - return 2; - } + if(handle == NULL) _exit(errbuf, 2); //begin processing the packets in this particular file int packets = -1; @@ -382,20 +444,14 @@ int main(int argc, char **argv) { while(packets != 0) packets = pcap_dispatch(handle, -1, (pcap_handler) my_callback, NULL); } catch(RuntimeException &ex) { - std::cerr << ex.asString() << std::endl << std::endl; - return 1; + _exit(ex.asString()); } pcap_close(handle); //close the pcap file // Print payloads ////////////////////////////////////////////////////////////////////////////////////////////// // Open output file: - std::string output = pcapFile; - output += ".report"; - std::ofstream out(output, std::ifstream::out); - std::string xmlStr; - anna::DataBlock db_aux(true); - - //out.write(str.c_str(), str.size()); + outputFile += ".report"; + std::ofstream out(outputFile, std::ifstream::out); for(payloads_it it = G_payloads.begin(); it != G_payloads.end(); it++) { LOGDEBUG( @@ -420,8 +476,7 @@ int main(int argc, char **argv) { try { G_codecMsg.decode(db_aux); } catch(RuntimeException &ex) { - std::cerr << ex.asString() << std::endl << std::endl; - return 1; + _exit(ex.asString()); } out << G_codecMsg.asXMLString(); @@ -429,10 +484,9 @@ int main(int argc, char **argv) { // Close output file: out.close(); - std::cout << "Open 'file.trace' in order to see process traces." << std::endl; - std::cout << "Open '" << output << "' to see conversion results." - << std::endl; - std::cout << std::endl; - return 0; + + std::string msg = "Open 'file.trace' in order to see process traces.\n"; + msg += "Open '"; msg += outputFile; msg += "' to see decoding results."; + _exit(msg, 0); } diff --git a/include/anna/diameter/codec/Avp.hpp b/include/anna/diameter/codec/Avp.hpp index c991703..164234e 100644 --- a/include/anna/diameter/codec/Avp.hpp +++ b/include/anna/diameter/codec/Avp.hpp @@ -385,22 +385,6 @@ protected: */ std::string getXMLdata(bool & isHex, const anna::diameter::stack::Format *stackFormat) const throw(); - /** - Interpret xml data in order to dump over the class content. - - \param avpNode Avp root node - */ - void fromXML(const anna::xml::Node* avpNode) throw(anna::RuntimeException); - - - /** - Encodes buffer with the class content. - - * @param buffer Raw data to be encoded - * @param size Size of raw data to be encoded - */ - void code(char* buffer, int &size) const throw(anna::RuntimeException); - /** Decodes Avp data part. @@ -690,6 +674,37 @@ public: const Unknown * getUnknown() const throw(anna::RuntimeException) { assertFormat("Unknown"); return a_Unknown; } + /** + Decodes buffer provided over class content. If an error ocurred, decoding will stop launching exception (fatal error) or a warning trace (perhaps the achieved + avp is valid against all odds then validation will go on). In case that validation is enabled (codec::Engine::ValidationMode) an exception will be launched + depending on validation depth (codec::Engine::ValidationDepth). + + Useful as serialization procedure with #code + + @param db Buffer data block processed + */ + void decode(const anna::DataBlock &db) throw(anna::RuntimeException); + + + /** + Interpret xml data in order to dump over the class content. + + \param avpNode Avp root node + */ + void fromXML(const anna::xml::Node* avpNode) throw(anna::RuntimeException); + + + /** + Encodes buffer with the class content. This method is internally used to encode diameter messages, but is declared as public, to allow + its use as serialization procedure. Then, it's assumed that this Avp is valid (validation shall be applied as part of a whole diameter + message but nothing will be verified now). + + * @param buffer Raw data to be encoded (shall be externally allocated) + * @param size Size of raw data to be encoded + */ + void code(char* buffer, int &size) const throw(anna::RuntimeException); + + // Helpers /** @@ -705,6 +720,26 @@ public: */ std::string asXMLString() const throw(); + /** + Comparison operator by mean serialization + + @param a1 Instance 1 for Avp class + @param a2 Instance 2 for Avp class + + @return Comparison result + */ + friend bool operator == (const Avp & a1, const Avp & a2) throw() { return (a1.asXMLString() == a2.asXMLString()); } + + /** + Match a regular expression (string pattern) regarding xml string serialization for this avp. + This works same as #Message::isLike + + @param pattern Pattern to match + + \return Returns the match result + */ + bool isLike(const std::string &pattern) const throw(); + /** Counts the number of ocurrences of Avps (first level) with the identifier provided diff --git a/include/anna/diameter/codec/Message.hpp b/include/anna/diameter/codec/Message.hpp index 87e1012..9f3c85f 100644 --- a/include/anna/diameter/codec/Message.hpp +++ b/include/anna/diameter/codec/Message.hpp @@ -750,7 +750,7 @@ public: std::string asXMLString() const throw(); /** - Comparison operator + Comparison operator by mean serialization @param m1 Instance 1 for Message class @param m2 Instance 2 for Message class diff --git a/include/anna/diameter/codec/functions.hpp b/include/anna/diameter/codec/functions.hpp index 9108b19..c50563a 100644 --- a/include/anna/diameter/codec/functions.hpp +++ b/include/anna/diameter/codec/functions.hpp @@ -73,7 +73,7 @@ namespace codec { typedef struct parent { // Used on decoding: - anna::diameter::CommandId MessageId; + anna::diameter::CommandId MessageId; std::string MessageName; std::vector AvpsId; diff --git a/include/anna/diameter/helpers/defines.hpp b/include/anna/diameter/helpers/defines.hpp index 7c16eef..5c8e97c 100644 --- a/include/anna/diameter/helpers/defines.hpp +++ b/include/anna/diameter/helpers/defines.hpp @@ -123,6 +123,9 @@ anna_diameter_helpers_define_appid(Diameter_Mobile_IPv6_Auth, 8); anna_diameter_helpers_define_appid(Diameter_QoS_Application, 9); // APPID__Diameter_QoS_Application // etc. anna_diameter_helpers_define_appid(3GPP_Rx, 16777236); // APPID__3GPP_Rx +anna_diameter_helpers_define_appid(3GPP_Gx, 16777238); // APPID__3GPP_Gx +anna_diameter_helpers_define_appid(3GPP_Sy, 16777302); // APPID__3GPP_Sy + // much more... } diff --git a/source/diameter/codec/Avp.cpp b/source/diameter/codec/Avp.cpp index 1a4378d..97437c1 100644 --- a/source/diameter/codec/Avp.cpp +++ b/source/diameter/codec/Avp.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -1313,6 +1314,17 @@ std::string Avp::getXMLdata(bool & isHex, const stack::Format *stackFormat) cons } +//------------------------------------------------------------------------------ +//---------------------------------------------------------------- Avp::decode() +//------------------------------------------------------------------------------ +void Avp::decode(const anna::DataBlock &db) throw(anna::RuntimeException) { + + parent_t parent; + parent.setMessage(CommandId(0,false), "No-Parent"); + decode(db, parent, NULL); +} + + //------------------------------------------------------------------------------ //--------------------------------------------------------------- Avp::fromXML() //------------------------------------------------------------------------------ @@ -1585,6 +1597,7 @@ anna::xml::Node* Avp::asXML(anna::xml::Node* parent) const throw() { return result; } + //------------------------------------------------------------------------------ //----------------------------------------------------------- Avp::asXMLString() //------------------------------------------------------------------------------ @@ -1593,3 +1606,11 @@ std::string Avp::asXMLString() const throw() { return anna::xml::Compiler().apply(asXML(&root)); } + +//------------------------------------------------------------------------------ +//---------------------------------------------------------------- Avp::isLike() +//------------------------------------------------------------------------------ +bool Avp::isLike(const std::string &pattern) const throw() { + anna::RegularExpression re(pattern); + return re.isLike(asXMLString()); +}