Fix local server for multiple applications
[anna.git] / diameter / stack / AvpRule.cpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 //------------------------------------------------------------------------------
10 //-------------------------------------------------------- included header files
11 //------------------------------------------------------------------------------
12
13 // Standard
14 #include <stdlib.h>
15
16 // Local
17 #include <anna/diameter/stack/AvpRule.hpp>
18 #include <anna/diameter/stack/Avp.hpp>
19 #include <anna/diameter/stack/Format.hpp>
20 #include <anna/diameter/functions.hpp>
21 #include <anna/diameter/stack/Dictionary.hpp>
22
23 #include <anna/config/defines.hpp>
24 #include <anna/core/RuntimeException.hpp>
25 #include <anna/xml/xml.hpp>
26
27 anna_assign_enum(anna::diameter::stack::AvpRule::Presence) = { "Fixed", "Mandatory", "Optional", NULL /* list end indicator */};
28
29
30 //------------------------------------------------------------------------------
31 //----------------------------------------------------------- AvpRule::setQual()
32 //------------------------------------------------------------------------------
33 void anna::diameter::stack::AvpRule::setQual(const std::string & q) throw(anna::RuntimeException) {
34   const char *asterisk = strstr(q.c_str(), "*");
35
36   if((q != "") && (asterisk == NULL))
37     throw anna::RuntimeException("Non-empty qualifier must contain '*'", ANNA_FILE_LOCATION);
38
39   a_qual = q;
40 }
41
42
43 //------------------------------------------------------------------------------
44 //-------------------------------------------------------- AvpRule::getAvpName()
45 //------------------------------------------------------------------------------
46 std::string anna::diameter::stack::AvpRule::getAvpName(void) const throw() {
47   const Avp * avp = a_dictionary->getAvp(a_avpId);
48   return avp->getName();
49 }
50
51 //------------------------------------------------------------------------------
52 //------------------------------------------------------------- AvpRule::isAny()
53 //------------------------------------------------------------------------------
54 bool anna::diameter::stack::AvpRule::isAny(void) const throw() {
55   const Avp * avp = a_dictionary->getAvp(a_avpId);
56   const Format * format = a_dictionary->getFormat(avp->getFormatName());
57   return format->isAny();
58 }
59
60
61 //------------------------------------------------------------------------------
62 //-------------------------------------------------------- AvpRule::getQualMin()
63 //------------------------------------------------------------------------------
64 int anna::diameter::stack::AvpRule::getQualMin(void) const throw() {
65   if(a_qual == "") {
66     if(isFixed() || isMandatory()) return 1;
67
68     if(isOptional()) return 0;
69   }
70
71   // Asterisk location
72   const char * c_qual = a_qual.c_str();
73   int asterisk_pos = strstr(c_qual, "*") - c_qual;
74
75   // '*', '*y'
76   if(asterisk_pos == 0) return 0;
77
78   // 'x*', 'x*y'
79   std::string min = a_qual.substr(0, asterisk_pos);  // 'x'
80   return (atoi(min.c_str()));
81 }
82
83
84
85 //------------------------------------------------------------------------------
86 //-------------------------------------------------------- AvpRule::getQualMax()
87 //------------------------------------------------------------------------------
88 int anna::diameter::stack::AvpRule::getQualMax(void) const throw() {
89   if(a_qual == "") return 1;
90
91   // Asterisk location
92   const char * c_qual = a_qual.c_str();
93   int asterisk_pos = strstr(c_qual, "*") - c_qual;
94
95   // '*', 'x*'
96   if(asterisk_pos == (a_qual.size() - 1)) return -1;  // inf
97
98   // '*y', 'x*y'
99   std::string max = a_qual.substr(asterisk_pos + 1, a_qual.size() - asterisk_pos - 1);  // 'y'
100   return (atoi(max.c_str()));
101 }
102
103
104 //------------------------------------------------------------------------------
105 //---------------------------------------------------------- AvpRule::asString()
106 //------------------------------------------------------------------------------
107 std::string anna::diameter::stack::AvpRule::asString(bool showPair) const throw() {
108   std::string trace = "No Avp rule defined";
109   const Avp * avp = a_dictionary->getAvp(a_avpId);
110
111   if(avp) {
112     trace = a_qual;
113     std::string s_open, s_close;
114
115     if(isFixed()) { s_open = "<"; s_close = ">"; }
116
117     if(isMandatory()) { s_open = "{"; s_close = "}"; }
118
119     if(isOptional()) { s_open = "["; s_close = "]"; }
120
121     trace += s_open;
122     trace += getAvpName(); // anna::diameter::functions::avpIdAsPairString(a_avpId);;
123     trace += s_close;
124
125     if(!showPair) return trace;
126
127     // Avoid ambiguous descriptions:
128     int qualSize = a_qual.size();
129     int tabSize = strlen(DICTIONARY_AVPRULE_TAB);
130     int NumberOfDots =   /* qual add */ ((qualSize > tabSize) ? tabSize : qualSize) +
131                                         /* max expected avp description size */   48 -
132                                         /* current trace length */                trace.size();
133
134     for(int k = 0; k < NumberOfDots; k++) trace += ".";
135
136     trace += anna::diameter::functions::avpIdAsPairString(avp->getId());
137   }
138
139   return (trace);
140 }
141
142
143 //------------------------------------------------------------------------------
144 //------------------------------------------------------------- AvpRule::asXML()
145 //------------------------------------------------------------------------------
146 anna::xml::Node* anna::diameter::stack::AvpRule::asXML(anna::xml::Node* parent) const throw() {
147 //   <!ELEMENT avprule EMPTY>
148 //   <!ATTLIST avprule id CDATA #REQUIRED type (Fixed | Mandatory | Optional) #REQUIRED qual CDATA #IMPLIED>
149   anna::xml::Node* result = parent->createChild("avprule");
150   result->createAttribute("id", getAvpName());
151   std::string type;
152
153   if(isFixed()) type = "Fixed";
154   else if(isMandatory()) type = "Mandatory";
155   else if(isOptional()) type = "Optional";
156
157   result->createAttribute("type", type);
158
159   if(a_qual != "") result->createAttribute("qual", a_qual);
160
161   return result;
162 }