pcapDecoder allows .hex files as input. Make public some Avp methods for serializatio...
authorEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Sat, 4 Apr 2015 01:35:17 +0000 (03:35 +0200)
committerEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Sat, 4 Apr 2015 01:35:17 +0000 (03:35 +0200)
example/diameter/launcher/main.cpp
example/diameter/pcapDecoder/main.cpp
include/anna/diameter/codec/Avp.hpp
include/anna/diameter/codec/Message.hpp
include/anna/diameter/codec/functions.hpp
include/anna/diameter/helpers/defines.hpp
source/diameter/codec/Avp.cpp

index 48b304d..7a08518 100644 (file)
@@ -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) {
index 8e3e866..65681d8 100644 (file)
@@ -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
-              << " <list of comma-separated xml dictionaries> <pcap file> [--ignore-flags: non-strict validation]"
-              << std::endl << std::endl;
-    return 1;
+    std::string msg = "Usage: "; msg += exec;
+    msg += " <dictionaries> <input file> [--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);
 }
 
index c991703..164234e 100644 (file)
@@ -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
 
index 87e1012..9f3c85f 100644 (file)
@@ -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
index 9108b19..c50563a 100644 (file)
@@ -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<anna::diameter::AvpId> AvpsId;
index 7c16eef..5c8e97c 100644 (file)
@@ -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...
 
 }
index 1a4378d..97437c1 100644 (file)
@@ -50,6 +50,7 @@
 #include <anna/diameter/stack/Engine.hpp>
 #include <anna/diameter/codec/Engine.hpp>
 #include <anna/core/functions.hpp>
+#include <anna/core/util/RegularExpression.hpp>
 
 #include <anna/core/tracing/Logger.hpp>
 #include <anna/core/functions.hpp>
@@ -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());
+}