Add nlohmann/json parser
[anna.git] / source / diameter / codec / EngineImpl.cpp
index af13e09..9d23e57 100644 (file)
@@ -1,37 +1,9 @@
-// ANNA - Anna is Not Nothingness Anymore
-//
-// (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
-//
-// http://redmine.teslayout.com/projects/anna-suite
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     *  Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Authors: eduardo.ramos.testillano@gmail.com
-//          cisco.tierra@gmail.com
+// ANNA - Anna is Not Nothingness Anymore                                                         //
+//                                                                                                //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
+//                                                                                                //
+// See project site at http://redmine.teslayout.com/projects/anna-suite                           //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
 
 
 // Local
 #include <anna/core/mt/Guard.hpp>
 
 
-
-namespace anna {
-namespace diameter {
-namespace codec {
-
-const char *MessageDTD = "\
-<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<!-- Diameter message DTD -->\n\
-\n\
-<!ELEMENT message (avp*)>\n\
-<!ELEMENT avp (avp*)>\n\
-\n\
-<!ATTLIST message version CDATA #IMPLIED name CDATA #IMPLIED code CDATA #IMPLIED flags CDATA #IMPLIED p-bit (yes | no) #IMPLIED e-bit (yes | no) #IMPLIED t-bit (yes | no) #IMPLIED application-id CDATA #REQUIRED hop-by-hop-id CDATA #IMPLIED end-by-end-id CDATA #IMPLIED>\n\
-<!--\n\
-   version: Diameter version. Sets '1' by default\n\
-   name:    Command name within working stack (dictionary identifier)\n\
-   p-bit:   (P)roxiable bit flag (yes, no). By default is 'no'\n\
-   e-bit:   (E)rror bit flag (yes, no). By default is 'no'\n\
-   t-bit:   Potentially re-(T)ransmitted bit flag (yes, no). By default is 'no'\n\
-\n\
-   In order to get more coding capabilities, command code and flags could be established instead of former fields,\n\
-    but neither of them are allowed if the other are present (and vice versa):\n\
-\n\
-   code:    Command code\n\
-   flags:   Command flags byte value (0-255) where standard bit set for flags is 'RPET rrrr': (R)equest, (P)roxiable, (E)rror, Potentially re-(T)ransmitted message and (r)eserved\n\
-\n\
-\n\
-   application-id:   Message application id\n\
-   hop-by-hop-id:    Message hop by hop id. Sets '0' by default\n\
-   end-by-end-id:    Message end by end id. Sets '0' by default\n\
--->\n\
-\n\
-<!ATTLIST avp name CDATA #IMPLIED code CDATA #IMPLIED vendor-code CDATA #IMPLIED flags CDATA #IMPLIED data CDATA #IMPLIED hex-data CDATA #IMPLIED alias CDATA #IMPLIED>\n\
-<!--\n\
-   name:   Avp name within working stack (dictionary identifier)\n\
-\n\
-   In order to get more coding capabilities, avp code, vendor-id and flags could be established instead of former avp name,\n\
-    but neither of them are allowed if 'name' is provided (and vice versa):\n\
-\n\
-   code:          Avp code\n\
-   vendor-code:   Avp vendor code\n\
-   flags:         Avp flags byte value (0-255) where standard bit set for flags is 'VMPr rrrr': (V)endor-specific, (M)andatory, end to end encry(P)tion and r(eserved)\n\
-   alias:         Descriptive/helper field for certain numeric data values. Aliases are defined at diameter dictionary, but are ignored (not checked) at xml message parsing\n\
-                  The reason to include it in dtd definition, is because xml messages traced by the diameter codec could add alias field for some Avps\n\
-\n\
-\n\
-   data:          Natural string representation for avp data. Specially applicable with numbers and printable strings, but also\n\
-                   useful for certain formats which could be easily understandable in such friendly/smart representation. We will\n\
-                   achieve different human-readable strings depending on data format:\n\
-\n\
-                     [ OctetString ] (if printable, but not recommended)\n\
-                     [ Integer32, Integer64, Unsigned32, Unsigned64, Float32, Float64 ] (normal number representation)\n\
-                     [ Time ] (NTP timestamp, normal number representation)\n\
-                     [ Address ] ('<type (IANA Address Family Number)>|<value>' representation; i.e. '1|192.168.0.1'(IPv4), '8|34616279266'(E164), etc.\n\
-                                 Type (and pipe) field could be avoided for IPv4 and IPv6 address types (a light parse checking is done: one colon for\n\
-                                 IPv6, one dot for IPv4). Internal engine always includes type on data field, which is also recommended for inputs.\n\
-                                 Currently, only IPv4, IPv6 and E164 address types have a known printable presentation, anyway using printable format\n\
-                                 for another types will encode the address value directly as E164 does)\n\
-                     [ UTF8String, DiameterIdentity, DiameterURI ] (printable)\n\
-                     [ IPFilterRule, QoSFilterRule ] (uses ASCII charset, printable)\n\
-\n\
-                     New application formats must define specific natural representation for internal raw data\n\
-\n\
-   hex-data:      Hexadecimal octet sequence representation (i.e. 'af012fb3', with even number of digits). Suitable for whatever kind\n\
-                   of diameter format, but mandatory for non printable information. OctetString usually transport non human-readable\n\
-                   data and should better be encoded within this field although being printable. Unknown avps (which fails identifying\n\
-                   provided name or code/vendor-code) must always use this representation.\n\
-\n\
-   Xml representation for decoded messages shows natural content except for 'OctetString' format and unknown avps. Anyway, when printable,\n\
-    OctetString could show such information at data field apart from hex-data, because many implementations use this format to transport\n\
-    readable-string data. In general, one of the data fields is mandatory except for 'Grouped' type (its data is another level of avps).\n\
-   Application-specific formats must decide the way to represent its contents, being recommended to use a natural representation if possible,\n\
-    because xml is read by humans with testing and monitoring purposes.\n\
--->\n\
-\n\
-";
-
-
-}
-}
-}
-
 using namespace anna::diameter::codec;
 
 
 //------------------------------------------------------------------------------
 //----------------------------------------------------- EngineImpl::EngineImpl()
 //------------------------------------------------------------------------------
-EngineImpl::EngineImpl(const char* className) :
+EngineImpl::EngineImpl(const char* className, const stack::Dictionary * dictionary) :
   anna::Component(className),
-  a_dictionary(NULL),
+  a_dictionary(dictionary),
   a_validationDepth(ValidationDepth::FirstError),
   a_validationMode(ValidationMode::AfterDecoding),
+  a_singleFailedAVP(true),
   a_ignoreFlags(false),
-  a_selectStackWithApplicationId(false),
   a_fixMode(FixMode::BeforeEncoding) {
   anna::diameter::sccs::activate();
   anna::xml::functions::initialize();
-  a_dtd.initialize(MessageDTD);
-}
-
-
-//------------------------------------------------------------------------------
-//-------------------------------------------------- EngineImpl::setDictionary()
-//------------------------------------------------------------------------------
-const anna::diameter::stack::Dictionary *EngineImpl::setDictionary(unsigned int stackId) throw() {
-  a_dictionary = (stack::Engine::instantiate()).getDictionary(stackId);
-  return a_dictionary;
 }
 
 
@@ -172,6 +52,9 @@ Avp* EngineImpl::createAvp(const AvpId *id) throw(anna::RuntimeException) {
   if((result = allocateAvp()) == NULL)
     throw anna::RuntimeException("diameter::codec::EngineImpl::allocateAvp returns NULL", ANNA_FILE_LOCATION);
 
+  // Sets engine
+  result->setEngine((Engine*)this);
+
   //result->clear(); better clear this at releaseAvp(), see class-help implementation example
   if(id) result->setId(*id);
 
@@ -189,6 +72,9 @@ Message* EngineImpl::createMessage(const CommandId *id) throw(anna::RuntimeExcep
   if((result = allocateMessage()) == NULL)
     throw anna::RuntimeException("diameter::codec::EngineImpl::allocateMessage returns NULL", ANNA_FILE_LOCATION);
 
+  // Sets engine
+  result->setEngine((Engine*)this);
+
   //result->clear(); better clear this at releaseMessage(), see class-help implementation example
   if(id) result->setId(*id);
 
@@ -201,7 +87,7 @@ Message* EngineImpl::createMessage(const CommandId *id) throw(anna::RuntimeExcep
 //------------------------------------------------------------------------------
 Message *EngineImpl::createMessage(const std::string & xmlPathFile) throw(anna::RuntimeException) {
   Message *result = createMessage();
-  result->loadXML(xmlPathFile);
+  result->loadXMLFile(xmlPathFile);
   return result;
 }
 
@@ -213,6 +99,8 @@ std::string EngineImpl::asString(void) const throw() {
   result += asText(a_validationDepth);
   result += "\nValidationMode: ";
   result += asText(a_validationMode);
+  result += "\nSingle Failed-AVP: ";
+  result += a_singleFailedAVP ? "yes" : "no";
   result += "\nIgnore flags: ";
   result += a_ignoreFlags ? "yes" : "no";
   result += "\nFixMode: ";
@@ -231,9 +119,10 @@ throw() {
   anna::xml::Node* result = parent->createChild("diameter.codec.EngineImpl");
   result->createAttribute("ValidationDepth", asText(a_validationDepth));
   result->createAttribute("ValidationMode", asText(a_validationMode));
+  result->createAttribute("SingleFailedAVP", a_singleFailedAVP ? "yes" : "no");
   result->createAttribute("IgnoreFlags", a_ignoreFlags ? "yes" : "no");
   result->createAttribute("FixMode", asText(a_fixMode));
-  anna::xml::Node* dictionary = result->createChild("EngineImpl.ActivatedDictionary");
+  result->createChild("EngineImpl.ActivatedDictionary");
 
   if(a_dictionary) a_dictionary->asXML(result);