Add pytest cache to gitignore
[anna.git] / source / diameter / helpers / dcca / functions.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 // Local
10 #include <anna/diameter/helpers/dcca/defines.hpp>
11 #include <anna/diameter/helpers/dcca/functions.hpp>
12 #include <anna/diameter/codec/Message.hpp>
13 #include <anna/diameter/codec/functions.hpp>
14 #include <anna/config/defines.hpp> // general types, decoding helpers (DECODE[2/3/4]BYTES_INDX_VALUETYPE), etc.
15 #include <anna/core/functions.hpp>
16
17 #include <anna/core/functions.hpp>
18 #include <anna/core/DataBlock.hpp>
19
20 // STL
21 #include <string>
22
23 using namespace anna;
24 using namespace anna::diameter::codec;
25 using namespace anna::diameter::helpers::dcca;
26
27
28
29 //static
30 const char anna::diameter::helpers::dcca::ChargingContextAndDomainSuffix::Data[] = "32251@3gpp.org";
31 const char anna::diameter::helpers::dcca::ChargingContextAndDomainSuffix::Voice[] = "OCS-CS@telefonica.com";
32 const char anna::diameter::helpers::dcca::ChargingContextAndDomainSuffix::Content[] = "OCS-Generic-Services@telefonica.com";
33 const char anna::diameter::helpers::dcca::ChargingContextAndDomainSuffix::SMS[] = "32274@3gpp.org";
34 const char anna::diameter::helpers::dcca::ChargingContextAndDomainSuffix::MMS[] = "32270@3gpp.org";
35
36
37 // getters
38 std::string anna::diameter::helpers::dcca::functions::getSubscriptionIdData(const anna::DataBlock & db, int subscriptionIdType) throw(anna::RuntimeException) {
39   if(db.getSize() < Message::HeaderLength)
40     throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION);
41
42   // Message datablock:
43   const char *avpsDB = db.getData() + Message::HeaderLength;
44   int avpsLen = db.getSize() - Message::HeaderLength;
45
46   // Auxiliar avp decoding:
47   AvpId _id;
48   char _flags;
49   int _length;
50   int type;
51   std::string _dataG /* grouped avp */, _data1 /* first avp within grouped */, _data2 /* second avp within grouped */;
52
53   const char * subscriptionIdPtr;
54   int pos = 1; // first subscriber to find
55   while((subscriptionIdPtr = diameter::codec::functions::findAVP(avpsDB, avpsLen, AVPID__Subscription_Id, pos))) {
56
57     // Decode data for the grouped avp found:
58     diameter::codec::functions::decodeAVP(subscriptionIdPtr, _id, _flags, _length, _dataG);
59     // Data (_dataG) consists in two mandatory Avps in ANY order:
60     //  - Subscription-Id-Type (Enumerated derived from Integer32)
61     //  - Subscription-Id-Data (UTF8String)
62
63     // First AVP within _dataG:
64     diameter::codec::functions::decodeAVP(_dataG.c_str(), _id, _flags, _length, _data1);
65
66     if (_id == diameter::helpers::dcca::AVPID__Subscription_Id_Type) {
67       type = DECODE4BYTES_INDX_VALUETYPE(_data1, 0, int);
68       if (type == subscriptionIdType) {
69         diameter::codec::functions::decodeAVP(_dataG.c_str() + 12, _id, _flags, _length, _data2);
70         if (_id == diameter::helpers::dcca::AVPID__Subscription_Id_Data) return _data2;
71       }
72     }
73     else if (_id == diameter::helpers::dcca::AVPID__Subscription_Id_Data) {
74       diameter::codec::functions::decodeAVP(_dataG.c_str() + 20, _id, _flags, _length, _data2);
75       if (_id == diameter::helpers::dcca::AVPID__Subscription_Id_Type) {
76         type = DECODE4BYTES_INDX_VALUETYPE(_data2, 0, int);
77         if (type == subscriptionIdType) return _data1;
78       }
79     }
80
81     pos++;
82   }
83
84
85   // Nothing retrieved:
86   return "";
87 }
88
89
90 std::string anna::diameter::helpers::dcca::functions::getServiceContextId(const anna::DataBlock & db, ChargingContext::_v &chargingContext) throw(anna::RuntimeException) {
91   if(db.getSize() < Message::HeaderLength)
92     throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION);
93
94   //anna::DataBlock avpsDB(db.getData() + Message::HeaderLength, db.getSize() - Message::HeaderLength);
95   //const char * serviceContextIdPtr = anna::diameter::codec::functions::findAVP(avpsDB, AVPID__Service_Context_Id);
96
97   const char *avpsDB = db.getData() + Message::HeaderLength;
98   int avpsLen = db.getSize() - Message::HeaderLength;
99   const char * serviceContextIdPtr = anna::diameter::codec::functions::findAVP(avpsDB, avpsLen, AVPID__Service_Context_Id);
100
101   if(serviceContextIdPtr == NULL)
102     throw anna::RuntimeException("Service-Context-Id AVP not found in DataBlock provided", ANNA_FILE_LOCATION);
103
104   // Decoded avp information:
105   AvpId _id;
106   char _flags;
107   int _length;
108   std::string result;
109   anna::diameter::codec::functions::decodeAVP(serviceContextIdPtr, _id, _flags, _length, result /* data-part */);
110   // Charging context detection:
111   chargingContext = ChargingContext::Unknown;
112
113   if(anna::functions::endsWith(result, ChargingContextAndDomainSuffix::Data))
114     chargingContext = ChargingContext::Data;
115   else if(anna::functions::endsWith(result, ChargingContextAndDomainSuffix::Voice))
116     chargingContext = ChargingContext::Voice;
117   else if(anna::functions::endsWith(result, ChargingContextAndDomainSuffix::Content))
118     chargingContext = ChargingContext::Content;
119   else if(anna::functions::endsWith(result, ChargingContextAndDomainSuffix::SMS))
120     chargingContext = ChargingContext::SMS;
121   else if(anna::functions::endsWith(result, ChargingContextAndDomainSuffix::MMS))
122     chargingContext = ChargingContext::MMS;
123
124   // ...
125   // future kind of traffic
126   return result;
127 }
128