ANNA Suite  2020b
Multipurpose development suite for Telco applications
functions.hpp
Go to the documentation of this file.
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 #ifndef anna_diameter_codec_functions_hpp
10 #define anna_diameter_codec_functions_hpp
11 
12 
13 // Project
16 #include <anna/xml/xml.hpp>
17 
18 // STL
19 #include <string>
20 #include <vector>
21 
22 
23 //------------------------------------------------------------------------------
24 //---------------------------------------------------------------------- #define
25 //------------------------------------------------------------------------------
26 
27 // Diameter words are four-byte size. Store n bytes requires 1 word more than former multiple of 4:
28 #define REQUIRED_WORDS(bytes) ((bytes)/4+((((bytes)%4)!=0)?1:0 ))
29 
30 
31 
32 namespace anna {
33 class DataBlock;
34 }
35 
36 
37 namespace anna {
38 
39 namespace diameter {
40 
41 namespace codec {
42 
43 
44 static const char *MessageDTD = "\
45 <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
46 <!-- Diameter message DTD -->\n\
47 \n\
48 <!ELEMENT message (avp*)>\n\
49 <!ELEMENT avp (avp*)>\n\
50 \n\
51 <!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-to-end-id CDATA #IMPLIED>\n\
52 <!--\n\
53  version: Diameter version. Sets '1' by default\n\
54  name: Command name within working stack (dictionary identifier)\n\
55  p-bit: (P)roxiable bit flag (yes, no). By default is 'no'\n\
56  e-bit: (E)rror bit flag (yes, no). By default is 'no'\n\
57  t-bit: Potentially re-(T)ransmitted bit flag (yes, no). By default is 'no'\n\
58 \n\
59  In order to get more coding capabilities, command code and flags could be established instead of former fields,\n\
60  but neither of them are allowed if the other are present (and vice versa):\n\
61 \n\
62  code: Command code\n\
63  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\
64 \n\
65 \n\
66  application-id: Message application id\n\
67  hop-by-hop-id: Message hop by hop id. Sets '0' by default\n\
68  end-to-end-id: Message end to end id. Sets '0' by default\n\
69 -->\n\
70 \n\
71 <!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\
72 <!--\n\
73  name: Avp name within working stack (dictionary identifier)\n\
74 \n\
75  In order to get more coding capabilities, avp code, vendor-id and flags could be established instead of former avp name,\n\
76  but neither of them are allowed if 'name' is provided (and vice versa):\n\
77 \n\
78  code: Avp code\n\
79  vendor-code: Avp vendor code\n\
80  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\
81  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\
82  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\
83 \n\
84 \n\
85  data: Natural string representation for avp data. Specially applicable with numbers and printable strings, but also\n\
86  useful for certain formats which could be easily understandable in such friendly/smart representation. We will\n\
87  achieve different human-readable strings depending on data format:\n\
88 \n\
89  [ OctetString ] (if printable, but not recommended)\n\
90  [ Integer32, Integer64, Unsigned32, Unsigned64, Float32, Float64 ] (normal number representation)\n\
91  [ Time ] (NTP timestamp, normal number representation)\n\
92  [ Address ] ('<type (IANA Address Family Number)>|<value>' representation; i.e. '1|192.168.0.1'(IPv4), '8|34616279266'(E164), etc.\n\
93  Type (and pipe) field could be avoided for IPv4 and IPv6 address types (a light parse checking is done: one colon for\n\
94  IPv6, one dot for IPv4). Internal engine always includes type on data field, which is also recommended for inputs.\n\
95  Currently, only IPv4, IPv6 and E164 address types have a known printable presentation, anyway using printable format\n\
96  for another types will encode the address value directly as E164 does)\n\
97  [ UTF8String, DiameterIdentity, DiameterURI ] (printable)\n\
98  [ IPFilterRule, QoSFilterRule ] (uses ASCII charset, printable)\n\
99 \n\
100  New application formats must define specific natural representation for internal raw data\n\
101 \n\
102  hex-data: Hexadecimal octet sequence representation (i.e. 'af012fb3', with even number of digits). Suitable for whatever kind\n\
103  of diameter format, but mandatory for non printable information. OctetString usually transport non human-readable\n\
104  data and should better be encoded within this field although being printable. Unknown avps (which fails identifying\n\
105  provided name or code/vendor-code) must always use this representation.\n\
106 \n\
107  Xml representation for decoded messages shows natural content except for 'OctetString' format and unknown avps. Anyway, when printable,\n\
108  OctetString could show such information at data field apart from hex-data, because many implementations use this format to transport\n\
109  readable-string data. In general, one of the data fields is mandatory except for 'Grouped' type (its data is another level of avps).\n\
110  Application-specific formats must decide the way to represent its contents, being recommended to use a natural representation if possible,\n\
111  because xml is read by humans with testing and monitoring purposes.\n\
112 -->\n\
113 \n\
114 ";
115 
116 
117 // Used for alarms, tracing and Failed-AVP construction:
118 typedef struct parent {
119 
120  // Used on decoding:
122  std::string MessageName;
123 
124  std::vector<anna::diameter::AvpId> AvpsId;
125  std::vector<std::string> AvpsName;
126 
127  void setMessage(const anna::diameter::CommandId & mid, const char *mname = NULL /* well known in validation */) ;
128  void addAvp(const anna::diameter::AvpId & aid, const char *aname = NULL /* well known in validation */) ;
129  std::string asString() const ;
130 
131 } parent_t;
132 
133 
134 
135 
136 struct functions {
137 
138  // getters & helpers
139  static CommandId getCommandId(const anna::DataBlock &) noexcept(false);
140  static ApplicationId getApplicationId(const anna::DataBlock &) noexcept(false);
141  static HopByHop getHopByHop(const anna::DataBlock &) noexcept(false);
142  static EndToEnd getEndToEnd(const anna::DataBlock &) noexcept(false);
143 
144  static bool requestBit(const anna::DataBlock &) noexcept(false);
145  static bool proxiableBit(const anna::DataBlock &) noexcept(false);
146  static bool errorBit(const anna::DataBlock &) noexcept(false);
147  static bool potentiallyReTransmittedMessageBit(const anna::DataBlock &) noexcept(false);
148 
149  static bool isRequest(const CommandId & cid) { return (cid.second); }
150  static bool isRequest(const anna::DataBlock & db) noexcept(false) { return requestBit(db); }
151 
152  static bool isAnswer(const CommandId & cid) { return (!isRequest(cid)); }
153  static bool isAnswer(const anna::DataBlock & db) noexcept(false) { return (!isRequest(db)); }
154 
155 
156 
169  static void decodeCommandHeader(const char *start, char & version, U24 & length, char & flags, CommandId & id, int & appId, int & hbh, int & ete) noexcept(false);
170 
180  static void decodeAVP(const char *start, AvpId & id, char & flags, int & length, std::string & data) noexcept(false);
181 
192  static const char * nextAVP(const char *avpsDB, int avpsLen, const char *start) noexcept(false);
193 
194  // /**
195  // * Gets the next AVP pointer reference starting from a first-avp datablock. It could be the first avp within
196  // * a command, or within an grouped avp.
197  // *
198  // * @param avpsDB AVPs set as datablock
199  // * @param start Point to start the search. Must be a valid avp start (point to the 32-bits avp code word).
200  // *
201  // * @return Pointer to the next AVP found. NULL if no more.
202  // */
203  // static const char * nextAVP(const anna::DataBlock & avpsDB, const char *start) noexcept(false);
204 
215  static const char *findAVP(const char *avpsDB, int avpsLen, const diameter::AvpId & id, int n = 1) noexcept(false);
216 
217  // /**
218  // * Gets the next AVP pointer reference within an AVPs set datablock with a certain AVP identification.
219  // *
220  // * @param avpsDB AVPs set as datablock
221  // * @param id Avp identification (code, vendorId).
222  // * @param n Ocurrence number (first avp, second avp, etc.). 1 by default.
223  // *
224  // * @return Pointer to first AVP found with identification provided. NULL if not found.
225  // */
226  // static const char * findAVP(const anna::DataBlock & avpsDB, const AvpId & id, int n = 1) noexcept(false);
227 
228 
229 
230  // modifiers
231  static void setHopByHop(anna::DataBlock &, HopByHop) noexcept(false);
232  static void setEndToEnd(anna::DataBlock &, EndToEnd) noexcept(false);
233  static void setPotentiallyReTransmittedMessageBit(const anna::DataBlock & db, bool activate = true) noexcept(false);
234 
235 
307  static void messageXmlDocumentFromXmlFile(anna::xml::DocumentFile &xmlDocument, const std::string & xmlPathFile) noexcept(false);
308 
321  static void messageXmlDocumentFromXmlString(anna::xml::DocumentMemory &xmlDocument, const std::string &xmlString) noexcept(false);
322 };
323 
324 
325 }
326 }
327 }
328 
329 
330 #endif
331 
static bool isRequest(const anna::DataBlock &db) noexcept(false)
Definition: functions.hpp:150
unsigned int EndToEnd
Definition: defines.hpp:70
unsigned int HopByHop
Definition: defines.hpp:68
std::vector< std::string > AvpsName
Definition: functions.hpp:125
void setMessage(const anna::diameter::CommandId &mid, const char *mname=NULL)
static bool isRequest(const CommandId &cid)
Definition: functions.hpp:149
std::vector< anna::diameter::AvpId > AvpsId
Definition: functions.hpp:124
struct anna::diameter::codec::parent parent_t
std::pair< S32, S32 > AvpId
Definition: defines.hpp:31
std::string asString() const
U32 U24
Definition: defines.hpp:96
static bool isAnswer(const anna::DataBlock &db) noexcept(false)
Definition: functions.hpp:153
std::string MessageName
Definition: functions.hpp:122
void addAvp(const anna::diameter::AvpId &aid, const char *aname=NULL)
Definition: app.hpp:12
unsigned int ApplicationId
Definition: defines.hpp:64
anna::diameter::CommandId MessageId
Definition: functions.hpp:121
Definition: DocumentFile.hpp:23
std::pair< U24, bool > CommandId
Definition: defines.hpp:32
static bool isAnswer(const CommandId &cid)
Definition: functions.hpp:152
Definition: DocumentMemory.hpp:23
Definition: DataBlock.hpp:24
Definition: functions.hpp:118
Definition: functions.hpp:136