LCOV - code coverage report
Current view: top level - stack - Dictionary.cpp (source / functions) Coverage Total Hit
Test: final-coverage.info Lines: 75.4 % 301 227
Test Date: 2026-08-11 23:06:37 Functions: 77.8 % 18 14

            Line data    Source code
       1              : #include <iostream>
       2              : /*
       3              :  ________________________________________________________________________
       4              : |                                                                        |
       5              : |       _ _                      _                         _             |
       6              : |      | (_)                    | |                       | |            |
       7              : |    __| |_  __ _ _ __ ___   ___| |_ ___ _ __ ___ ___   __| | ___  ___   |
       8              : |   / _` | |/ _` | '_ ` _ \ / _ \ __/ _ \ '__/ __/ _ \ / _` |/ _ \/ __|  |
       9              : |  | (_| | | (_| | | | | | |  __/ ||  __/ | | (_| (_) | (_| |  __/ (__   |
      10              : |   \__,_|_|\__,_|_| |_| |_|\___|\__\___|_|  \___\___/ \__,_|\___|\___|  |
      11              : |                                                                        |
      12              : |________________________________________________________________________|
      13              : 
      14              : C++ CODEC FOR DIAMETER PROTOCOL (RFC 6733)
      15              : Version 0.0.z
      16              : https://github.com/testillano/diametercodec
      17              : 
      18              : Licensed under the MIT License <http://opensource.org/licenses/MIT>.
      19              : SPDX-License-Identifier: MIT
      20              : Copyright (c) 2021 Eduardo Ramos
      21              : 
      22              : Permission is hereby  granted, free of charge, to any  person obtaining a copy
      23              : of this software and associated  documentation files (the "Software"), to deal
      24              : in the Software  without restriction, including without  limitation the rights
      25              : to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
      26              : copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
      27              : furnished to do so, subject to the following conditions:
      28              : 
      29              : The above copyright notice and this permission notice shall be included in all
      30              : copies or substantial portions of the Software.
      31              : 
      32              : THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
      33              : IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
      34              : FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
      35              : AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
      36              : LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      37              : OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
      38              : SOFTWARE.
      39              : */
      40              : 
      41              : // Project
      42              : #include <ert/diametercodec/stack/Dictionary.hpp>
      43              : #include <ert/tracing/Logger.hpp>
      44              : 
      45              : namespace ert {
      46              : namespace diametercodec {
      47              : namespace stack {
      48              : 
      49          146 : void Dictionary::initialize() {
      50          146 :     formats_.clear();
      51          146 :     vendors_.clear();
      52          146 :     avps_.clear();
      53          146 :     commands_.clear();
      54          146 :     vendor_names_.clear();
      55          146 :     avp_names_.clear();
      56          146 :     command_names_.clear();
      57              : 
      58              :     // RFC6733 Diameter Formats harcoding:
      59              :     // Basic diameter types
      60          146 :     Format OctetString(this), Integer32(this), Integer64(this), Unsigned32(this), Unsigned64(this), Float32(this),
      61          146 :         Float64(this), Grouped(this);
      62          146 :     OctetString.setType(Format::Type::OctetString);
      63          146 :     Integer32.setType(Format::Type::Integer32);
      64          146 :     Integer64.setType(Format::Type::Integer64);
      65          146 :     Unsigned32.setType(Format::Type::Unsigned32);
      66          146 :     Unsigned64.setType(Format::Type::Unsigned64);
      67          146 :     Float32.setType(Format::Type::Float32);
      68          146 :     Float64.setType(Format::Type::Float64);
      69          146 :     Grouped.setType(Format::Type::Grouped);
      70              : 
      71          146 :     addFormat(OctetString);
      72          146 :     addFormat(Integer32);
      73          146 :     addFormat(Integer64);
      74          146 :     addFormat(Unsigned32);
      75          146 :     addFormat(Unsigned64);
      76          146 :     addFormat(Float32);
      77          146 :     addFormat(Float64);
      78          146 :     addFormat(Grouped);
      79              : 
      80              :     // Derived diameter types
      81          146 :     Format Address(this), Time(this), UTF8String(this), DiameterIdentity(this), DiameterURI(this), Enumerated(this),
      82          146 :         IPFilterRule(this), QoSFilterRule(this);
      83          146 :     Address.setType(Format::Type::Address);
      84          146 :     Address.setParentName(OctetString.getName());
      85          146 :     Time.setType(Format::Type::Time);
      86          146 :     Time.setParentName(OctetString.getName());
      87          146 :     UTF8String.setType(Format::Type::UTF8String);
      88          146 :     UTF8String.setParentName(OctetString.getName());
      89          146 :     DiameterIdentity.setType(Format::Type::DiameterIdentity);
      90          146 :     DiameterIdentity.setParentName(OctetString.getName());
      91          146 :     DiameterURI.setType(Format::Type::DiameterURI);
      92          146 :     DiameterURI.setParentName(OctetString.getName());
      93          146 :     Enumerated.setType(Format::Type::Enumerated);
      94          146 :     Enumerated.setParentName(Integer32.getName());
      95          146 :     IPFilterRule.setType(Format::Type::IPFilterRule);
      96          146 :     IPFilterRule.setParentName(OctetString.getName());
      97          146 :     QoSFilterRule.setType(Format::Type::QoSFilterRule);
      98          146 :     QoSFilterRule.setParentName(OctetString.getName());
      99              : 
     100          146 :     addFormat(Address);
     101          146 :     addFormat(Time);
     102          146 :     addFormat(UTF8String);
     103          146 :     addFormat(DiameterIdentity);
     104          146 :     addFormat(DiameterURI);
     105          146 :     addFormat(Enumerated);
     106          146 :     addFormat(IPFilterRule);
     107          146 :     addFormat(QoSFilterRule);
     108              : 
     109              :     // Generic AVP format:
     110          146 :     Format Any(this);
     111          146 :     Any.setType(Format::Type::Any);
     112          146 :     addFormat(Any, true /*reserved*/);
     113              : 
     114              :     // Generic AVP:
     115          146 :     Avp genericAvp(this);
     116          146 :     genericAvp.setCode(0);
     117          146 :     genericAvp.setVendorId(0 /*Vendor::Code::Ietf*/);
     118          146 :     genericAvp.setName("AVP");
     119          146 :     genericAvp.setFormatName(Any.getName());
     120          146 :     genericAvp.setVBit(false);
     121          146 :     genericAvp.setMBit(false);
     122          146 :     addAvp(genericAvp);
     123          146 : }
     124              : 
     125         2482 : void Dictionary::addFormat(const Format &format, bool reserved) {
     126         2482 :     if (!reserved && format.isReserved()) {
     127              :         std::string s_ex =
     128            0 :             ert::tracing::Logger::asString("Format type '%s' is reserved for internal use", format.getName().c_str());
     129            0 :         throw std::runtime_error(s_ex);
     130            0 :     }
     131              : 
     132         2482 :     const Format *found = getFormat(format.getName());
     133         2482 :     if (found) {
     134              :         // Update:
     135            0 :         LOGINFORMATIONAL(std::string trace = "Updated format '"; trace += format.getName(); trace += "'";
     136              :                          ert::tracing::Logger::informational(trace, ERT_FILE_LOCATION););
     137              :     }
     138              : 
     139         2482 :     formats_[format.getName()] = format;
     140         2482 : }
     141              : 
     142          876 : void Dictionary::addVendor(const Vendor &vendor) {
     143          876 :     vendors_[vendor.getCode()] = vendor;
     144          876 :     vendor_names_[vendor.getName()] = getVendor(vendor.getCode());
     145          876 : }
     146              : 
     147        15792 : void Dictionary::addAvp(const Avp &avp) {
     148        15792 :     avps_[avp.getId()] = avp;
     149        15792 :     avp_names_[avp.getName()] = getAvp(avp.getId());
     150        15792 : }
     151              : 
     152         2044 : void Dictionary::addCommand(const Command &command) {
     153         2044 :     commands_[command.getId()] = command;
     154         2044 :     command_names_[command.getName()] = getCommand(command.getId());
     155         2044 : }
     156              : 
     157       450507 : const Format *Dictionary::getFormat(const std::string &formatName) const {
     158       450507 :     auto it = formats_.find(formatName);
     159              : 
     160       450507 :     if (it != formats_.end()) return &(it->second);
     161              : 
     162         2482 :     return (nullptr);
     163              : }
     164              : 
     165          876 : const Vendor *Dictionary::getVendor(core::S32 vendorId) const {
     166          876 :     auto it = vendors_.find(vendorId);
     167              : 
     168          876 :     if (it != vendors_.end()) return &(it->second);
     169              : 
     170            0 :     return (nullptr);
     171              : }
     172              : 
     173            0 : const Vendor *Dictionary::getVendor(const std::string &vendorName) const {
     174            0 :     auto it = vendor_names_.find(vendorName);
     175              : 
     176            0 :     if (it != vendor_names_.end()) return (it->second);
     177              : 
     178            0 :     return (nullptr);
     179              : }
     180              : 
     181        16054 : Avp *Dictionary::getAvp(const core::AvpId &avpId) const {
     182        16054 :     auto it = avps_.find(avpId);
     183              : 
     184        16054 :     if (it != avps_.end()) return (Avp *)&(it->second);
     185              : 
     186            5 :     return (nullptr);
     187              : }
     188              : 
     189        33559 : Avp *Dictionary::getAvp(const std::string &avpName) const {
     190        33559 :     auto it = avp_names_.find(avpName);
     191              : 
     192        33559 :     if (it != avp_names_.end()) return (Avp *)(it->second);
     193              : 
     194            2 :     return (nullptr);
     195              : }
     196              : 
     197         2044 : Command *Dictionary::getCommand(const core::CommandId &commandId) const {
     198         2044 :     auto it = commands_.find(commandId);
     199              : 
     200         2044 :     if (it != commands_.end()) return (Command *)&(it->second);
     201              : 
     202            0 :     return (nullptr);
     203              : }
     204              : 
     205            0 : Command *Dictionary::getCommand(const std::string &commandName) const {
     206            0 :     auto it = command_names_.find(commandName);
     207              : 
     208            0 :     if (it != command_names_.end()) return (Command *)(it->second);
     209              : 
     210            0 :     return (nullptr);
     211              : }
     212              : 
     213            0 : nlohmann::json Dictionary::asJson(void) const {
     214            0 :     nlohmann::json result;
     215              : 
     216            0 :     result["name"] = name_;
     217              : 
     218              :     // Formats
     219            0 :     for (const auto &it : formats_) {
     220            0 :         if (it.second.isReserved()) continue;
     221            0 :         if (it.second.isRFC6733()) continue;  // only user-defined formats are shown
     222            0 :         result["format"].push_back(it.second.asJson());
     223              :     }
     224              : 
     225              :     // Vendors
     226            0 :     for (const auto &it : vendors_) result["vendor"].push_back(it.second.asJson());
     227              : 
     228              :     // Avps
     229            0 :     for (const auto &it : avps_) {
     230            0 :         if (it.second.getFormat()->isAny()) continue;  // Generic AVP not shown
     231              : 
     232            0 :         result["avp"].push_back(it.second.asJson());
     233              :     }
     234              : 
     235              :     // Commands
     236            0 :     for (const auto &it : commands_) result["command"].push_back(it.second.asJson());
     237              : 
     238            0 :     return result;
     239            0 : }
     240              : 
     241            0 : void Dictionary::extractFormats(const nlohmann::json &doc) {
     242            0 :     for (const auto &it : doc) {
     243            0 :         Format aux(this);  // set everything below (even empty, zeroed, etc.) to avoid reset() function
     244              : 
     245              :         // Mandatory
     246            0 :         auto name_it = it.find("name");
     247            0 :         auto ptype_it = it.find("parent-type");
     248              : 
     249              :         // Assignments:
     250            0 :         aux.setName(*name_it);
     251            0 :         aux.setParentName(*ptype_it);
     252              : 
     253              :         // New entry:
     254            0 :         addFormat(aux);
     255            0 :     }
     256            0 : }
     257              : 
     258          146 : void Dictionary::extractVendors(const nlohmann::json &doc) {
     259         1898 :     for (const auto &it : doc) {
     260          876 :         Vendor aux;  // set everything below (even empty, zeroed, etc.) to avoid reset() function
     261              : 
     262              :         // Mandatory
     263          876 :         auto name_it = it.find("name");
     264          876 :         auto code_it = it.find("code");
     265              : 
     266              :         // Assignments:
     267          876 :         aux.setCode(*code_it);
     268          876 :         aux.setName(*name_it);
     269              : 
     270              :         // New entry:
     271          876 :         addVendor(aux);
     272          876 :     }
     273          146 : }
     274              : 
     275          158 : void Dictionary::extractAvps(const nlohmann::json &doc) {
     276        15804 :     for (const auto &it : doc) {
     277        15646 :         Avp aux(this);  // set everything below (even empty, zeroed, etc.) to avoid reset() function
     278              : 
     279              :         // Mandatory
     280        15646 :         auto name_it = it.find("name");
     281        15646 :         std::string name = *name_it;
     282        15646 :         auto code_it = it.find("code");
     283        15646 :         auto vendor_name_it = it.find("vendor-name");
     284        15646 :         core::S32 vendorCode = 0; /* IETF by default */
     285        15646 :         auto single_it = it.find("single");
     286              : 
     287              :         // Optionals
     288        15646 :         auto vbit_it = it.find("v-bit");
     289        15646 :         auto mbit_it = it.find("m-bit");
     290              : 
     291              :         // Vendor ?
     292        15646 :         if (vendor_name_it != it.end()) {
     293            0 :             std::string c_name = *vendor_name_it;
     294            0 :             auto v_it = vendor_names_.find(c_name);
     295              : 
     296            0 :             if (v_it == vendor_names_.end()) {
     297              :                 std::string s_ex = ert::tracing::Logger::asString(
     298            0 :                     "Vendor '%s', referenced at '%s' avp definition, not found at xml", c_name, name.c_str());
     299            0 :                 throw std::runtime_error(s_ex);
     300            0 :             }
     301              : 
     302            0 :             aux.setVendorName(c_name);
     303            0 :             vendorCode = ((*v_it).second)->getCode();
     304            0 :         }
     305              : 
     306              :         // Assignments:
     307        15646 :         aux.setCode(*code_it);
     308        15646 :         aux.setVendorId(vendorCode);
     309        15646 :         aux.setName(*name_it);
     310        15646 :         aux.setVBit((vbit_it != it.end()) ? bool(*vbit_it) : false);
     311        15646 :         aux.setMBit((mbit_it != it.end()) ? bool(*mbit_it) : false);
     312              : 
     313              :         // Check vendor specific bit:
     314        15646 :         if (vendorCode && !aux.vBit()) {
     315              :             std::string s_ex = ert::tracing::Logger::asString(
     316              :                 "Flag rules for vendor specific bit (mustnot) at '%s' avp definicion, are incompatible with non-zeroed "
     317              :                 "vendor id %d",
     318            0 :                 name.c_str(), vendorCode);
     319            0 :             throw std::runtime_error(s_ex);
     320            0 :         }
     321              : 
     322        15646 :         if (!vendorCode && aux.vBit()) {
     323              :             std::string s_ex = ert::tracing::Logger::asString(
     324              :                 "Flag rules for vendor specific bit (must) at '%s' avp definicion, are incompatible with zeroed vendor "
     325              :                 "id %d",
     326            0 :                 name.c_str(), vendorCode);
     327            0 :             throw std::runtime_error(s_ex);
     328            0 :         }
     329              : 
     330        15646 :         if (single_it != it.end()) {
     331        13018 :             auto f_it = (*single_it).find("format");  // mandatory
     332        13018 :             std::string formatName = *f_it;
     333        13018 :             auto enum_it = (*single_it).find("enum");
     334        13018 :             auto label_it = (*single_it).find("label");
     335              : 
     336              :             // Assignments:
     337        13018 :             const Format *format = getFormat(formatName);
     338              : 
     339        13018 :             if (!format) {
     340              :                 std::string s_ex = ert::tracing::Logger::asString(
     341              :                     "Format '%s', referenced at '%s' avp definition, not found at dictionary (neither xml nor RFC6733 "
     342              :                     "diameter format types)",
     343            0 :                     formatName.c_str(), name.c_str());
     344            0 :                 throw std::runtime_error(s_ex);
     345            0 :             }
     346              : 
     347        13018 :             aux.setFormatName(formatName);
     348              : 
     349        13018 :             if (enum_it != (*single_it).end()) {
     350         3358 :                 std::string s_enum = *enum_it;
     351              : 
     352         3358 :                 if (!format->isEnumerated()) {
     353              :                     std::string s_ex =
     354              :                         ert::tracing::Logger::asString("Enumerated literal '%s' is not allowed for '%s' avp format",
     355            0 :                                                        s_enum.c_str(), formatName.c_str());
     356            0 :                     throw std::runtime_error(s_ex);
     357            0 :                 }
     358              : 
     359         3358 :                 aux.setEnums(s_enum.c_str());
     360         3358 :             }
     361              : 
     362        13018 :             if (label_it != (*single_it).end()) {
     363        24820 :                 for (const auto &l_it : *label_it) {
     364        20732 :                     std::string data = *(l_it.find("data"));
     365        20732 :                     std::string alias = *(l_it.find("alias"));
     366              :                     // Assignment:
     367        20732 :                     aux.addLabel(data, alias);
     368        20732 :                 }
     369              :             }
     370        13018 :         } else {  // grouped
     371              :             // Assignments:
     372         5256 :             aux.setFormatName(Format::Type::asText(Format::Type::Grouped));
     373              :             // Wait for avprule insertion, because we need complete avp reference pool (*)
     374              :         }
     375              : 
     376              :         // New entry:
     377        15646 :         addAvp(aux);
     378        15646 :     }
     379              : 
     380              :     // Now process grouped ones:
     381        15804 :     for (const auto &it : doc) {
     382        15646 :         auto name_it = it.find("name");
     383        15646 :         auto grouped_it = it.find("grouped");
     384              : 
     385        15646 :         auto a_it = avp_names_.find(*name_it);
     386        15646 :         Avp *gavp = (Avp *)((*a_it).second);
     387              : 
     388        15646 :         if (!gavp) continue;  // it could be mising (a redefinition could have removed it)
     389              : 
     390        15646 :         const Format *format = gavp->getFormat();
     391              : 
     392              :         // Avprule updating:
     393        15646 :         if (format->isGrouped()) {  // double check
     394         2628 :             auto avprule_it = grouped_it->find("avprule");
     395         2628 :             AvpRule auxAvpRule(this);  // set everything below (even empty, zeroed, etc.) to avoid reset() function
     396        12264 :             for (const auto &it : *avprule_it) {
     397         9636 :                 std::string name = *(it.find("name"));
     398         9636 :                 std::string type = *(it.find("type"));
     399         9636 :                 auto qual_it = it.find("qual");  // optional
     400              : 
     401         9636 :                 const Avp *avp = getAvp(name);
     402         9636 :                 if (avp == nullptr) {
     403              :                     std::string s_ex = ert::tracing::Logger::asString(
     404              :                         "Avp '%s', referenced at avp rule definition within grouped '%s', not found at xml",
     405            0 :                         name.c_str(), std::string(*name_it).c_str());
     406            0 :                     throw std::runtime_error(s_ex);
     407            0 :                 }
     408              : 
     409         9636 :                 auxAvpRule.setAvpId(avp->getId());
     410         9636 :                 auxAvpRule.setPresence(AvpRule::Presence::asEnum(type));
     411         9636 :                 auxAvpRule.setQual((qual_it != it.end()) ? *qual_it : "");
     412         9636 :                 gavp->addAvpRule(auxAvpRule);
     413         9636 :             }
     414         2628 :         }
     415              :     }
     416              : 
     417              :     // Check avp loops between grouped avps:
     418              : 
     419              :     // In order to avoid loops, we could force to define grouped avps which children
     420              :     //  had been previously defined at xml file. In this way, is imposible to get a loop:
     421              :     //   C = ...
     422              :     //   D = ...
     423              :     //   A = grouped of B,C,D -> error, B unknown
     424              :     //   B = grouped of A,F -> with former definition, would become a loop
     425              :     //
     426              :     // But this supposes a restriction at json configuration (specific order).
     427              :     // The other way is an internal check: a grouped AVP won't have descendants within
     428              :     //  its ascendants. Then we will check all grouped avps in this way:
     429              :     //
     430              :     // 1. Searching for another grouped avps which are parents for this avp.
     431              :     // 2. If these are children (even this avp(*)) at avp definition, then a loop is detected.
     432              :     //
     433              :     // Example 1: (1) Analyzing 'A', found parent 'B' / (2) 'B' is already children of 'A'
     434              :     //       A -> B
     435              :     //            C
     436              :     //            D
     437              :     //       ...
     438              :     //       B -> A -> loop !!
     439              :     //            F
     440              :     //
     441              :     // (*) Example 2: (1) Analyzing 'A', found parent 'A' / (2) 'A' is already children of 'A'
     442              :     //       A -> B
     443              :     //            C
     444              :     //            D
     445              :     //            A -> loop !!
     446              :     //
     447        17246 :     for (auto it = avps_.begin(); it != avps_.end(); it++) {
     448        17088 :         const Avp &avp = (*it).second;
     449              : 
     450        17088 :         if (!((avp.getFormat())->isGrouped())) continue;
     451              : 
     452       310428 :         for (auto it_p = avps_.begin(); it_p != avps_.end(); it_p++) {
     453       307584 :             const Avp &avp_p = (*it_p).second;
     454              : 
     455       307584 :             if (!((avp_p.getFormat())->isGrouped())) continue;
     456              : 
     457        51192 :             if (avp_p.isChild(avp.getId())) {
     458         1896 :                 if (avp.isChild(avp_p.getId())) {
     459            0 :                     std::string s_ex;
     460              : 
     461            0 :                     if (it != it_p)
     462            0 :                         s_ex = ert::tracing::Logger::asString("Loop detected between grouped avps '%s' and '%s'",
     463            0 :                                                               avp.getName().c_str(), avp_p.getName().c_str());
     464              :                     else
     465            0 :                         s_ex = ert::tracing::Logger::asString("Loop within grouped avp '%s': cannot contain itself !!",
     466            0 :                                                               avp.getName().c_str());
     467              : 
     468            0 :                     throw std::runtime_error(s_ex);
     469            0 :                 }  // parent is children of (ref): loop !
     470              :             }  // parent found
     471              :         }  // search parents
     472              :     }  // search grouped avps (ref)
     473          158 : }
     474              : 
     475          146 : void Dictionary::extractCommands(const nlohmann::json &doc) {
     476         4234 :     for (const auto &it : doc) {
     477         2044 :         Command aux;  // set everything below (even empty, zeroed, etc.) to avoid reset() function
     478              : 
     479              :         // Mandatory
     480         2044 :         auto name_it = it.find("name");
     481         2044 :         auto code_it = it.find("code");
     482         2044 :         auto avprule_it = it.find("avprule");
     483              : 
     484              :         // Optionals
     485         2044 :         auto appid_it = it.find("application-id");
     486         2044 :         auto rbit_it = it.find("r-bit");
     487         2044 :         auto pbit_it = it.find("p-bit");
     488              : 
     489              :         // Assignments:
     490         2044 :         aux.setName(*name_it);
     491         2044 :         aux.setCode(*code_it);
     492         2044 :         aux.setApplicationId((appid_it != it.end()) ? core::U32(*appid_it) : 0);
     493         2044 :         aux.setRequest((rbit_it != it.end()) ? bool(*rbit_it) : false);
     494         2044 :         aux.setPBit((pbit_it != it.end()) ? bool(*pbit_it) : false);
     495              : 
     496         2044 :         AvpRule auxAvpRule(this);  // set everything below (even empty, zeroed, etc.) to avoid reset() function
     497        49640 :         for (const auto &it : *avprule_it) {
     498        23798 :             std::string name = *(it.find("name"));
     499        23798 :             std::string type = *(it.find("type"));
     500        23798 :             auto qual_it = it.find("qual");  // optional
     501              : 
     502        23798 :             const Avp *avp = getAvp(name);
     503        23798 :             if (avp == nullptr) {
     504              :                 std::string s_ex = ert::tracing::Logger::asString(
     505              :                     "Avp '%s', referenced at avp rule definition within command '%s', not found at xml", name.c_str(),
     506            0 :                     std::string(*name_it).c_str());
     507            0 :                 throw std::runtime_error(s_ex);
     508            0 :             }
     509              : 
     510        23798 :             auxAvpRule.setAvpId(avp->getId());
     511        23798 :             auxAvpRule.setPresence(AvpRule::Presence::asEnum(type));
     512        23798 :             auxAvpRule.setQual((qual_it != it.end()) ? *qual_it : "");
     513        23798 :             aux.addAvpRule(auxAvpRule);
     514        23798 :         }
     515              : 
     516              :         // New entry:
     517         2044 :         addCommand(aux);
     518         2044 :     }
     519          146 : }
     520              : 
     521          158 : void Dictionary::load(const nlohmann::json &json) {
     522              :     // Mandatory
     523          158 :     auto name_it = json.find("name");
     524          158 :     name_ = *name_it;
     525              : 
     526              :     // Optional
     527          158 :     auto formats_it = json.find("format");
     528          158 :     if (formats_it != json.end() && formats_it->is_array()) {
     529            0 :         extractFormats(*formats_it);
     530              :     }
     531              : 
     532          158 :     auto vendors_it = json.find("vendor");
     533          158 :     if (vendors_it != json.end() && vendors_it->is_array()) {
     534          146 :         extractVendors(*vendors_it);
     535              :     }
     536              : 
     537          158 :     auto avps_it = json.find("avp");
     538          158 :     if (avps_it != json.end() && avps_it->is_array()) {
     539          158 :         extractAvps(*avps_it);
     540              :     }
     541              : 
     542          158 :     auto commands_it = json.find("command");
     543          158 :     if (commands_it != json.end() && commands_it->is_array()) {
     544          146 :         extractCommands(*commands_it);
     545              :     }
     546          158 : }
     547              : 
     548              : }  // namespace stack
     549              : }  // namespace diametercodec
     550              : }  // namespace ert
        

Generated by: LCOV version 2.0-1