Fix subscription-id decoding function
[anna.git] / source / diameter / helpers / dcca / functions.cpp
index 89850a9..ccb1d80 100644 (file)
@@ -39,43 +39,51 @@ std::string anna::diameter::helpers::dcca::functions::getSubscriptionIdData(cons
   if(db.getSize() < Message::HeaderLength)
     throw anna::RuntimeException("Not enough bytes to cover command header length", ANNA_FILE_LOCATION);
 
-  //anna::DataBlock avpsDB(db.getData() + Message::HeaderLength, db.getSize() - Message::HeaderLength);
+  // Message datablock:
   const char *avpsDB = db.getData() + Message::HeaderLength;
   int avpsLen = db.getSize() - Message::HeaderLength;
-  std::string result = "";
-  bool found = false;
-  int pos = 1; // first avp
-  const char * subscriptionIdPtr;
-  const char * subscriptionIdDataPtr;
-  int type;
-  // Decoded avp information:
+
+  // Auxiliar avp decoding:
   AvpId _id;
   char _flags;
   int _length;
-  std::string _dataG /* grouped */, _data;
-
-  while(!found) {
-    //subscriptionIdPtr = diameter::codec::functions::findAVP(avpsDB, AVPID__Subscription_Id, pos);
-    subscriptionIdPtr = diameter::codec::functions::findAVP(avpsDB, avpsLen, AVPID__Subscription_Id, pos);
+  int type;
+  std::string _dataG /* grouped avp */, _data1 /* first avp within grouped */, _data2 /* second avp within grouped */;
 
-    if(!subscriptionIdPtr) return result;
+  const char * subscriptionIdPtr;
+  int pos = 1; // first subscriber to find
+  while((subscriptionIdPtr = diameter::codec::functions::findAVP(avpsDB, avpsLen, AVPID__Subscription_Id, pos))) {
 
-    // Look up type:
+    // Decode data for the grouped avp found:
     diameter::codec::functions::decodeAVP(subscriptionIdPtr, _id, _flags, _length, _dataG);
-    // Data is Fixed Subscription-Id-Type (Enumerated derived from Integer32) and then Fixed Subscription-Id-Data (UTF8String):
-    // No need to find Subscription-Id-Type, it's always the first:
-    diameter::codec::functions::decodeAVP(_dataG.c_str(), _id, _flags, _length, _data);
-    // Enumerated:
-    int type = DECODE4BYTES_INDX_VALUETYPE(_data, 0, int);
-    found = (type == subscriptionIdType);
+    // Data (_dataG) consists in two mandatory Avps in ANY order:
+    //  - Subscription-Id-Type (Enumerated derived from Integer32)
+    //  - Subscription-Id-Data (UTF8String)
+
+    // First AVP within _dataG:
+    diameter::codec::functions::decodeAVP(_dataG.c_str(), _id, _flags, _length, _data1);
+
+    if (_id == diameter::helpers::dcca::AVPID__Subscription_Id_Type) {
+      type = DECODE4BYTES_INDX_VALUETYPE(_data1, 0, int);
+      if (type == subscriptionIdType) {
+        diameter::codec::functions::decodeAVP(_dataG.c_str() + 12, _id, _flags, _length, _data2);
+        if (_id == diameter::helpers::dcca::AVPID__Subscription_Id_Data) return _data2;
+      }
+    }
+    else if (_id == diameter::helpers::dcca::AVPID__Subscription_Id_Data) {
+      diameter::codec::functions::decodeAVP(_dataG.c_str() + 20, _id, _flags, _length, _data2);
+      if (_id == diameter::helpers::dcca::AVPID__Subscription_Id_Type) {
+        type = DECODE4BYTES_INDX_VALUETYPE(_data2, 0, int);
+        if (type == subscriptionIdType) return _data1;
+      }
+    }
+
     pos++;
   }
 
-  // No need to find Subscription-Id-Data within _dataG, it's always the second, and the first takes always 3 words (no vendorID):
-  subscriptionIdDataPtr = _dataG.c_str() + 12;
-  diameter::codec::functions::decodeAVP(subscriptionIdDataPtr, _id, _flags, _length, result);
-  // Result:
-  return result;
+
+  // Nothing retrieved:
+  return "";
 }