pcapDecoder allows .hex files as input. Make public some Avp methods for serializatio...
[anna.git] / example / diameter / pcapDecoder / main.cpp
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);
 }