Browse code

sbc:cc: passing config namespace to call control module

this allows several independent invocations of the same call control
as it can separate its call variables by the config namespace

Stefan Sayer authored on 03/10/2011 20:02:00
Showing 14 changed files
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- * Copyright (C) 2010 Stefan Sayer
2
+ * Copyright (C) 2010-2011 Stefan Sayer
3 3
  *
4 4
  * This file is part of SEMS, a free SIP media server.
5 5
  *
... ...
@@ -1084,6 +1084,7 @@ bool SBCDialog::CCStart(const AmSipRequest& req) {
1084 1084
     CCInterface& cc_if = *cc_it;
1085 1085
 
1086 1086
     AmArg di_args,ret;
1087
+    di_args.push(cc_if.cc_name);
1087 1088
     di_args.push(getLocalTag());
1088 1089
     di_args.push((ArgObject*)&call_profile);
1089 1090
     di_args.push(AmArg());
... ...
@@ -1102,7 +1103,23 @@ bool SBCDialog::CCStart(const AmSipRequest& req) {
1102 1103
 
1103 1104
     di_args.push(cc_timer_id); // current timer ID
1104 1105
 
1105
-    (*cc_mod)->invoke("start", di_args, ret);
1106
+    try {
1107
+      (*cc_mod)->invoke("start", di_args, ret);
1108
+    } catch (const AmArg::OutOfBoundsException& e) {
1109
+      ERROR("OutOfBoundsException executing call control interface start "
1110
+	    "module '%s' named '%s', parameters '%s'\n",
1111
+	    cc_if.cc_module.c_str(), cc_if.cc_name.c_str(),
1112
+	    AmArg::print(di_args).c_str());
1113
+      dlg.reply(req, 500, SIP_REPLY_SERVER_INTERNAL_ERROR);
1114
+      return false;
1115
+    } catch (const AmArg::TypeMismatchException& e) {
1116
+      ERROR("TypeMismatchException executing call control interface start "
1117
+	    "module '%s' named '%s', parameters '%s'\n",
1118
+	    cc_if.cc_module.c_str(), cc_if.cc_name.c_str(),
1119
+	    AmArg::print(di_args).c_str());
1120
+      dlg.reply(req, 500, SIP_REPLY_SERVER_INTERNAL_ERROR);
1121
+      return false;
1122
+    }
1106 1123
 
1107 1124
     // evaluate ret
1108 1125
     if (isArgArray(ret)) {
... ...
@@ -1185,9 +1202,10 @@ void SBCDialog::CCConnect(const AmSipReply& reply) {
1185 1202
 
1186 1203
   for (vector<CCInterface>::iterator cc_it=call_profile.cc_interfaces.begin();
1187 1204
        cc_it != call_profile.cc_interfaces.end(); cc_it++) {
1188
-    //    CCInterface& cc_if = *cc_it;
1205
+    CCInterface& cc_if = *cc_it;
1189 1206
 
1190 1207
     AmArg di_args,ret;
1208
+    di_args.push(cc_if.cc_name);                // cc name
1191 1209
     di_args.push(getLocalTag());                 // call ltag
1192 1210
     di_args.push((ArgObject*)&call_profile);     // call profile
1193 1211
     di_args.push(AmArg());                       // timestamps
... ...
@@ -1199,7 +1217,24 @@ void SBCDialog::CCConnect(const AmSipReply& reply) {
1199 1217
       di_args.back().push((int)0);
1200 1218
     di_args.push(other_id);                      // other leg ltag
1201 1219
 
1202
-    (*cc_mod)->invoke("connect", di_args, ret);
1220
+
1221
+    try {
1222
+      (*cc_mod)->invoke("connect", di_args, ret);
1223
+    } catch (const AmArg::OutOfBoundsException& e) {
1224
+      ERROR("OutOfBoundsException executing call control interface connect "
1225
+	    "module '%s' named '%s', parameters '%s'\n",
1226
+	    cc_if.cc_module.c_str(), cc_if.cc_name.c_str(),
1227
+	    AmArg::print(di_args).c_str());
1228
+      stopCall();
1229
+      return;
1230
+    } catch (const AmArg::TypeMismatchException& e) {
1231
+      ERROR("TypeMismatchException executing call control interface connect "
1232
+	    "module '%s' named '%s', parameters '%s'\n",
1233
+	    cc_if.cc_module.c_str(), cc_if.cc_name.c_str(),
1234
+	    AmArg::print(di_args).c_str());
1235
+      stopCall();
1236
+      return;
1237
+    }
1203 1238
 
1204 1239
     cc_mod++;
1205 1240
   }
... ...
@@ -1210,9 +1245,10 @@ void SBCDialog::CCEnd() {
1210 1245
 
1211 1246
   for (vector<CCInterface>::iterator cc_it=call_profile.cc_interfaces.begin();
1212 1247
        cc_it != call_profile.cc_interfaces.end(); cc_it++) {
1213
-    //    CCInterface& cc_if = *cc_it;
1248
+    CCInterface& cc_if = *cc_it;
1214 1249
 
1215 1250
     AmArg di_args,ret;
1251
+    di_args.push(cc_if.cc_name);
1216 1252
     di_args.push(getLocalTag());                 // call ltag
1217 1253
     di_args.push((ArgObject*)&call_profile);
1218 1254
     di_args.push(AmArg());                       // timestamps
... ...
@@ -1222,7 +1258,20 @@ void SBCDialog::CCEnd() {
1222 1258
     di_args.back().push((int)call_connect_ts.tv_usec);
1223 1259
     di_args.back().push((int)call_end_ts.tv_sec);
1224 1260
     di_args.back().push((int)call_end_ts.tv_usec);
1225
-    (*cc_mod)->invoke("end", di_args, ret);
1261
+
1262
+    try {
1263
+      (*cc_mod)->invoke("end", di_args, ret);
1264
+    } catch (const AmArg::OutOfBoundsException& e) {
1265
+      ERROR("OutOfBoundsException executing call control interface end "
1266
+	    "module '%s' named '%s', parameters '%s'\n",
1267
+	    cc_if.cc_module.c_str(), cc_if.cc_name.c_str(),
1268
+	    AmArg::print(di_args).c_str());
1269
+    } catch (const AmArg::TypeMismatchException& e) {
1270
+      ERROR("TypeMismatchException executing call control interface end "
1271
+	    "module '%s' named '%s', parameters '%s'\n",
1272
+	    cc_if.cc_module.c_str(), cc_if.cc_name.c_str(),
1273
+	    AmArg::print(di_args).c_str());
1274
+    }
1226 1275
 
1227 1276
     cc_mod++;
1228 1277
   }
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- * Copyright (C) 2010 Stefan Sayer
2
+ * Copyright (C) 2010-2011 Stefan Sayer
3 3
  *
4 4
  * This file is part of SEMS, a free SIP media server.
5 5
  *
... ...
@@ -96,38 +96,24 @@ int CallTimer::onLoad() {
96 96
 
97 97
 void CallTimer::invoke(const string& method, const AmArg& args, AmArg& ret)
98 98
 {
99
-  DBG("CallTimer: %s(%s)\n", method.c_str(), AmArg::print(args).c_str());
100
-
101
-    if(method == "start"){
102
-
103
-      // INFO("--------------------------------------------------------------\n");
104
-      // INFO("Got call control start ltag '%s' start_ts %i.%i\n",
105
-      // 	   args.get(0).asCStr(), args[2][0].asInt(), args[2][1].asInt());
106
-      // INFO("---- dumping CC values ----\n");
107
-      // for (AmArg::ValueStruct::const_iterator it =
108
-      // 	     args.get(CC_API_PARAMS_CFGVALUES).begin();
109
-      //               it != args.get(CC_API_PARAMS_CFGVALUES).end(); it++) {
110
-      // 	INFO("    CDR value '%s' = '%s'\n", it->first.c_str(), it->second.asCStr());
111
-      // }
112
-      // INFO("--------------------------------------------------------------\n");
113
-
114
-      // ltag, call profile, timestamps, [[key: val], ...], timer_id
115
-      args.assertArrayFmt("soaui");
116
-
117
-      start(args[CC_API_PARAMS_CFGVALUES],
118
-	    args[CC_API_PARAMS_TIMERID].asInt(),  ret);
119
-
120
-    } else if(method == "connect"){
121
-      // unused
122
-    } else if(method == "end"){
123
-      // unused
124
-    } else if(method == "_list"){
125
-      ret.push("start");
126
-      ret.push("connect");
127
-      ret.push("end");
128
-    }
129
-    else
130
-	throw AmDynInvoke::NotImplemented(method);
99
+  // DBG("CallTimer: %s(%s)\n", method.c_str(), AmArg::print(args).c_str());
100
+
101
+  if (method == "start"){
102
+
103
+    start(args[CC_API_PARAMS_CFGVALUES],
104
+	  args[CC_API_PARAMS_TIMERID].asInt(),  ret);
105
+
106
+  } else if (method == "connect"){
107
+    // unused
108
+  } else if (method == "end"){
109
+    // unused
110
+  } else if (method == "_list"){
111
+    ret.push("start");
112
+    ret.push("connect");
113
+    ret.push("end");
114
+  }
115
+  else
116
+    throw AmDynInvoke::NotImplemented(method);
131 117
 }
132 118
 
133 119
 void CallTimer::start(const AmArg& values, int timer_id, AmArg& res) {
... ...
@@ -33,7 +33,7 @@
33 33
 
34 34
 #include <string.h>
35 35
 
36
-#define SBCVAR_PARALLEL_CALLS_UUID "pcalls::uuid"
36
+#define SBCVAR_PARALLEL_CALLS_UUID "uuid"
37 37
 
38 38
 unsigned int CCParallelCalls::refuse_code = 402;
39 39
 string CCParallelCalls::refuse_reason = "Too Many Simultaneous Calls";
... ...
@@ -71,41 +71,38 @@ void CCParallelCalls::invoke(const string& method, const AmArg& args, AmArg& ret
71 71
 {
72 72
   // DBG("CCParallelCalls: %s(%s)\n", method.c_str(), AmArg::print(args).c_str());
73 73
 
74
-    if(method == "start"){
75
-
76
-      // ltag, call profile, timestamps, [[key: val], ...], timer_id
77
-      args.assertArrayFmt("soaui");
78
-      SBCCallProfile* call_profile =
79
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
80
-
81
-      start(args[CC_API_PARAMS_LTAG].asCStr(), call_profile,
82
-	    args[CC_API_PARAMS_CFGVALUES], ret);
83
-
84
-    } else if(method == "connect"){
85
-      // no action
86
-
87
-    } else if(method == "end"){
88
-
89
-      // ltag, call_profile, end_ts_sec, end_ts_usec
90
-      args.assertArrayFmt("soa"); 
91
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
92
-      SBCCallProfile* call_profile =
93
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
94
-
95
-      end(args[CC_API_PARAMS_LTAG].asCStr(), call_profile);
96
-
97
-    } else if(method == CC_INTERFACE_MAND_VALUES_METHOD){
98
-      ret.push("uuid");
99
-    } else if(method == "_list"){
100
-      ret.push("start");
101
-      ret.push("connect");
102
-      ret.push("end");
103
-    }
104
-    else
105
-	throw AmDynInvoke::NotImplemented(method);
74
+  if(method == "start"){
75
+    SBCCallProfile* call_profile =
76
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
77
+
78
+    start(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
79
+	  args[CC_API_PARAMS_LTAG].asCStr(), call_profile,
80
+	  args[CC_API_PARAMS_CFGVALUES], ret);
81
+    
82
+  } else if(method == "connect"){
83
+    // no action
84
+
85
+  } else if(method == "end"){
86
+    args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
87
+    SBCCallProfile* call_profile =
88
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
89
+
90
+    end(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
91
+	args[CC_API_PARAMS_LTAG].asCStr(), call_profile);
92
+
93
+  } else if(method == CC_INTERFACE_MAND_VALUES_METHOD){
94
+    ret.push("uuid");
95
+  } else if(method == "_list"){
96
+    ret.push("start");
97
+    ret.push("connect");
98
+    ret.push("end");
99
+  }
100
+  else
101
+    throw AmDynInvoke::NotImplemented(method);
106 102
 }
107 103
 
108
-void CCParallelCalls::start(const string& ltag, SBCCallProfile* call_profile,
104
+void CCParallelCalls::start(const string& cc_namespace,
105
+			    const string& ltag, SBCCallProfile* call_profile,
109 106
 			    const AmArg& values, AmArg& res) {
110 107
   if (!call_profile) return;
111 108
 
... ...
@@ -122,7 +119,7 @@ void CCParallelCalls::start(const string& ltag, SBCCallProfile* call_profile,
122 119
 
123 120
   string uuid = values["uuid"].asCStr();
124 121
 
125
-  call_profile->cc_vars[SBCVAR_PARALLEL_CALLS_UUID] = uuid;
122
+  call_profile->cc_vars[cc_namespace+"::"+SBCVAR_PARALLEL_CALLS_UUID] = uuid;
126 123
 
127 124
   unsigned int max_calls = 1; // default
128 125
   if (values.hasMember("max_calls") && isArgCStr(values["max_calls"])) {
... ...
@@ -171,16 +168,17 @@ void CCParallelCalls::start(const string& ltag, SBCCallProfile* call_profile,
171 168
 
172 169
 }
173 170
 
174
-void CCParallelCalls::end(const string& ltag, SBCCallProfile* call_profile) {
171
+void CCParallelCalls::end(const string& cc_namespace, const string& ltag,
172
+			  SBCCallProfile* call_profile) {
175 173
   if (!call_profile) return;
176 174
 
177
-  SBCVarMapIteratorT vars_it = call_profile->cc_vars.find(SBCVAR_PARALLEL_CALLS_UUID);
175
+  SBCVarMapIteratorT vars_it = call_profile->cc_vars.find(cc_namespace+"::"+SBCVAR_PARALLEL_CALLS_UUID);
178 176
   if (vars_it == call_profile->cc_vars.end() || !isArgCStr(vars_it->second)) {
179 177
     ERROR("internal: could not find UUID for ending call '%s'\n", ltag.c_str());
180 178
     return;
181 179
   }
182 180
   string uuid = vars_it->second.asCStr();
183
-  call_profile->cc_vars.erase(SBCVAR_PARALLEL_CALLS_UUID);
181
+  call_profile->cc_vars.erase(cc_namespace+"::"+SBCVAR_PARALLEL_CALLS_UUID);
184 182
 
185 183
   unsigned int new_call_count  = 0;
186 184
 
... ...
@@ -47,9 +47,11 @@ class CCParallelCalls : public AmDynInvoke
47 47
 
48 48
   static CCParallelCalls* _instance;
49 49
 
50
-  void start(const string& ltag, SBCCallProfile* call_profile,
50
+  void start(const string& cc_namespace,
51
+	     const string& ltag, SBCCallProfile* call_profile,
51 52
 	     const AmArg& values, AmArg& res);
52
-  void end(const string& ltag, SBCCallProfile* call_profile);
53
+  void end(const string& cc_namespace,
54
+	   const string& ltag, SBCCallProfile* call_profile);
53 55
 
54 56
  public:
55 57
   CCParallelCalls();
... ...
@@ -34,7 +34,7 @@
34 34
 
35 35
 #include <string.h>
36 36
 
37
-#define SBCVAR_PREPAID_UUID "prepaid::uuid"
37
+#define SBCVAR_PREPAID_UUID "uuid"
38 38
 
39 39
 class PrepaidFactory : public AmDynInvokeFactory
40 40
 {
... ...
@@ -91,122 +91,92 @@ int Prepaid::onLoad() {
91 91
 
92 92
 void Prepaid::invoke(const string& method, const AmArg& args, AmArg& ret)
93 93
 {
94
-  DBG("Prepaid: %s(%s)\n", method.c_str(), AmArg::print(args).c_str());
94
+  // DBG("Prepaid: %s(%s)\n", method.c_str(), AmArg::print(args).c_str());
95 95
 
96
-    if(method == "start"){
96
+  if(method == "start"){
97
+    args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
98
+    SBCCallProfile* call_profile =
99
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
97 100
 
98
-
99
-      // INFO("--------------------------------------------------------------\n");
100
-      // INFO("Got call control start ltag '%s' start_ts %i.%i\n",
101
-      // 	   args.get(0).asCStr(), args[2][0].asInt(), args[2][1].asInt());
102
-      // INFO("---- dumping CC values ----\n");
103
-      // for (AmArg::ValueStruct::const_iterator it =
104
-      // 	     args.get(CC_API_PARAMS_CFGVALUES).begin();
105
-      //               it != args.get(CC_API_PARAMS_CFGVALUES).end(); it++) {
106
-      // 	INFO("    CDR value '%s' = '%s'\n", it->first.c_str(), it->second.asCStr());
107
-      // }
108
-      // INFO("--------------------------------------------------------------\n");
109
-
110
-      // ltag, call profile, timestamps, [[key: val], ...], timer_id
111
-      args.assertArrayFmt("soaui");
112
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
113
-      SBCCallProfile* call_profile =
114
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
115
-
116
-      start(args[CC_API_PARAMS_LTAG].asCStr(),
117
-	    call_profile,
118
-	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_SEC].asInt(),
119
-	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_USEC].asInt(),
120
-	    args[CC_API_PARAMS_CFGVALUES],
121
-	    args[CC_API_PARAMS_TIMERID].asInt(),  ret);
122
-
123
-    } else if(method == "connect"){
124
-      // INFO("--------------------------------------------------------------\n");
125
-      // INFO("Got CDR connect ltag '%s' other_ltag '%s', connect_ts %i.%i\n",
126
-      // 	   args[CC_API_PARAMS_LTAG].asCStr(),
127
-      //           args[CC_API_PARAMS_OTHERID].asCStr(),
128
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
129
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt());
130
-      // INFO("--------------------------------------------------------------\n");
131
-      // ltag, call_profile, other_ltag, connect_ts_sec, connect_ts_usec
132
-      args.assertArrayFmt("soas");
133
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
134
-      SBCCallProfile* call_profile =
135
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
136
-
137
-      connect(args[CC_API_PARAMS_LTAG].asCStr(),
138
-	      call_profile,
139
-	      args[CC_API_PARAMS_OTHERID].asCStr(),
140
-	      args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
141
-	      args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt());
142
-
143
-    } else if(method == "end"){
144
-      // INFO("--------------------------------------------------------------\n");
145
-      // INFO("Got CDR end ltag %s end_ts %i.%i\n",
146
-      // 	   args[CC_API_PARAMS_LTAG].asCStr(),
147
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_SEC].asInt(),
148
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_USEC].asInt());
149
-      // INFO("--------------------------------------------------------------\n");
150
-
151
-      // ltag, call_profile, end_ts_sec, end_ts_usec
152
-      args.assertArrayFmt("soa"); 
153
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
154
-      SBCCallProfile* call_profile =
155
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
156
-
157
-      end(args[CC_API_PARAMS_LTAG].asCStr(),
101
+    start(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
102
+	  args[CC_API_PARAMS_LTAG].asCStr(),
158 103
 	  call_profile,
159 104
 	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_SEC].asInt(),
160 105
 	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_USEC].asInt(),
161
-	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
162
-	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt(),
163
-	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_SEC].asInt(),
164
-	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_USEC].asInt()
165
-	  );
166
-    } else if(method == CC_INTERFACE_MAND_VALUES_METHOD){
167
-
168
-      ret.push("uuid");
169
-
170
-    } else if (method == "getCredit"){
171
-      assertArgCStr(args.get(0));
172
-      bool found;
173
-      ret.push(getCredit(args.get(0).asCStr(), found));
174
-      ret.push(found);
175
-    } else if (method == "subtractCredit"){
176
-      assertArgCStr(args.get(0));
177
-      assertArgInt(args.get(1));
178
-      bool found;
179
-      ret.push(subtractCredit(args.get(0).asCStr(),
180
-			      args.get(1).asInt(),
181
-			      found));
182
-      ret.push(found);
183
-    } else if (method == "addCredit"){
184
-      assertArgCStr(args.get(0));
185
-      assertArgInt(args.get(1));
186
-      ret.push(addCredit(args.get(0).asCStr(),
187
-			 args.get(1).asInt()));	
188
-    } else if (method == "setCredit"){
189
-      assertArgCStr(args.get(0));
190
-      assertArgInt(args.get(1));
191
-      ret.push(setCredit(args.get(0).asCStr(),
192
-			 args.get(1).asInt()));	
193
-    } else if (method == "_list"){
194
-      ret.push("start");
195
-      ret.push("connect");
196
-      ret.push("end");
197
-
198
-      ret.push("getCredit");
199
-      ret.push("subtractCredit");
200
-      ret.push("setCredit");
201
-      ret.push("addCredit");
202
-    }
203
-    else
204
-	throw AmDynInvoke::NotImplemented(method);
106
+	  args[CC_API_PARAMS_CFGVALUES],
107
+	  args[CC_API_PARAMS_TIMERID].asInt(),  ret);
108
+
109
+  } else if(method == "connect"){
110
+    SBCCallProfile* call_profile =
111
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
112
+
113
+    connect(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
114
+	    args[CC_API_PARAMS_LTAG].asCStr(),
115
+	    call_profile,
116
+	    args[CC_API_PARAMS_OTHERID].asCStr(),
117
+	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
118
+	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt());
119
+
120
+  } else if(method == "end"){
121
+    args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
122
+    SBCCallProfile* call_profile =
123
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
124
+
125
+    end(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
126
+	args[CC_API_PARAMS_LTAG].asCStr(),
127
+	call_profile,
128
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_SEC].asInt(),
129
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_USEC].asInt(),
130
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
131
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt(),
132
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_SEC].asInt(),
133
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_USEC].asInt()
134
+	);
135
+  } else if(method == CC_INTERFACE_MAND_VALUES_METHOD){
136
+
137
+    ret.push("uuid");
138
+
139
+  } else if (method == "getCredit"){
140
+    assertArgCStr(args.get(0));
141
+    bool found;
142
+    ret.push(getCredit(args.get(0).asCStr(), found));
143
+    ret.push(found);
144
+  } else if (method == "subtractCredit"){
145
+    assertArgCStr(args.get(0));
146
+    assertArgInt(args.get(1));
147
+    bool found;
148
+    ret.push(subtractCredit(args.get(0).asCStr(),
149
+			    args.get(1).asInt(),
150
+			    found));
151
+    ret.push(found);
152
+  } else if (method == "addCredit"){
153
+    assertArgCStr(args.get(0));
154
+    assertArgInt(args.get(1));
155
+    ret.push(addCredit(args.get(0).asCStr(),
156
+		       args.get(1).asInt()));	
157
+  } else if (method == "setCredit"){
158
+    assertArgCStr(args.get(0));
159
+    assertArgInt(args.get(1));
160
+    ret.push(setCredit(args.get(0).asCStr(),
161
+		       args.get(1).asInt()));	
162
+  } else if (method == "_list"){
163
+    ret.push("start");
164
+    ret.push("connect");
165
+    ret.push("end");
166
+
167
+    ret.push("getCredit");
168
+    ret.push("subtractCredit");
169
+    ret.push("setCredit");
170
+    ret.push("addCredit");
171
+  }
172
+  else
173
+    throw AmDynInvoke::NotImplemented(method);
205 174
 }
206 175
 
207
-void Prepaid::start(const string& ltag, SBCCallProfile* call_profile,
208
-		       int start_ts_sec, int start_ts_usec,
209
-		       const AmArg& values, int timer_id, AmArg& res) {
176
+void Prepaid::start(const string& cc_name, const string& ltag,
177
+		    SBCCallProfile* call_profile,
178
+		    int start_ts_sec, int start_ts_usec,
179
+		    const AmArg& values, int timer_id, AmArg& res) {
210 180
 
211 181
   if (!call_profile) return;
212 182
 
... ...
@@ -224,7 +194,7 @@ void Prepaid::start(const string& ltag, SBCCallProfile* call_profile,
224 194
 
225 195
   string uuid = values["uuid"].asCStr();
226 196
 
227
-  call_profile->cc_vars[SBCVAR_PREPAID_UUID] = uuid;
197
+  call_profile->cc_vars[cc_name+"::"+SBCVAR_PREPAID_UUID] = uuid;
228 198
 
229 199
   bool found;
230 200
   int credit = getCredit(uuid, found);
... ...
@@ -249,13 +219,15 @@ void Prepaid::start(const string& ltag, SBCCallProfile* call_profile,
249 219
   res_cmd[SBC_CC_TIMER_TIMEOUT] = credit;
250 220
 }
251 221
 
252
-void Prepaid::connect(const string& ltag, SBCCallProfile* call_profile,
222
+void Prepaid::connect(const string& cc_name, 
223
+		      const string& ltag, SBCCallProfile* call_profile,
253 224
 		      const string& other_tag,
254 225
 		      int connect_ts_sec, int connect_ts_usec) {
255 226
   // DBG("call '%s' gets connected\n", ltag.c_str());
256 227
 }
257 228
 
258
-void Prepaid::end(const string& ltag, SBCCallProfile* call_profile,
229
+void Prepaid::end(const string& cc_name, 
230
+		  const string& ltag, SBCCallProfile* call_profile,
259 231
 		  int start_ts_sec, int start_ts_usec,
260 232
 		  int connect_ts_sec, int connect_ts_usec,
261 233
 		  int end_ts_sec, int end_ts_usec) {
... ...
@@ -263,7 +235,9 @@ void Prepaid::end(const string& ltag, SBCCallProfile* call_profile,
263 235
   if (!call_profile) return;
264 236
 
265 237
   // get uuid
266
-  SBCVarMapIteratorT vars_it = call_profile->cc_vars.find(SBCVAR_PREPAID_UUID);
238
+  SBCVarMapIteratorT vars_it = call_profile->
239
+    cc_vars.find(cc_name+"::"+SBCVAR_PREPAID_UUID);
240
+
267 241
   if (vars_it == call_profile->cc_vars.end() || !isArgCStr(vars_it->second)) {
268 242
     ERROR("internal: could not find UUID for call '%s' - "
269 243
 	  "not accounting (start_ts %i.%i, connect_ts %i.%i, end_ts %i.%i)\n",
... ...
@@ -274,7 +248,7 @@ void Prepaid::end(const string& ltag, SBCCallProfile* call_profile,
274 248
   }
275 249
 
276 250
   string uuid = vars_it->second.asCStr();
277
-  call_profile->cc_vars.erase(SBCVAR_PREPAID_UUID);
251
+  call_profile->cc_vars.erase(cc_name+"::"+SBCVAR_PREPAID_UUID);
278 252
 
279 253
   if (!connect_ts_sec || !end_ts_sec) {
280 254
     DBG("call not connected - uuid '%s' ltag '%s'\n", uuid.c_str(), ltag.c_str());
... ...
@@ -54,13 +54,13 @@ class Prepaid : public AmDynInvoke
54 54
   int setCredit(string pin, int amount);
55 55
 
56 56
 
57
-  void start(const string& ltag, SBCCallProfile* call_profile,
57
+  void start(const string& cc_name, const string& ltag, SBCCallProfile* call_profile,
58 58
 	     int start_ts_sec, int start_ts_usec, const AmArg& values,
59 59
 	     int timer_id, AmArg& res);
60
-  void connect(const string& ltag, SBCCallProfile* call_profile,
60
+  void connect(const string& cc_name, const string& ltag, SBCCallProfile* call_profile,
61 61
 	       const string& other_ltag,
62 62
 	       int connect_ts_sec, int connect_ts_usec);
63
-  void end(const string& ltag, SBCCallProfile* call_profile,
63
+  void end(const string& cc_name, const string& ltag, SBCCallProfile* call_profile,
64 64
 	   int start_ts_sec, int start_ts_usec,
65 65
 	   int connect_ts_sec, int connect_ts_usec,
66 66
 	   int end_ts_sec, int end_ts_usec);
... ...
@@ -38,7 +38,7 @@ using namespace XmlRpc;
38 38
 
39 39
 #include <string.h>
40 40
 
41
-#define SBCVAR_PREPAID_XMLRPC_UUID "prepaid_xmlrpc::uuid"
41
+#define SBCVAR_PREPAID_XMLRPC_UUID "uuid"
42 42
 
43 43
 class PrepaidXMLRPCFactory : public AmDynInvokeFactory
44 44
 {
... ...
@@ -100,110 +100,79 @@ int PrepaidXMLRPC::onLoad() {
100 100
 
101 101
 void PrepaidXMLRPC::invoke(const string& method, const AmArg& args, AmArg& ret)
102 102
 {
103
-  DBG("PrepaidXMLRPC: %s(%s)\n", method.c_str(), AmArg::print(args).c_str());
103
+  // DBG("PrepaidXMLRPC: %s(%s)\n", method.c_str(), AmArg::print(args).c_str());
104 104
 
105
-    if(method == "start"){
105
+  if(method == "start"){
106
+    args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
107
+    SBCCallProfile* call_profile =
108
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
106 109
 
107
-
108
-      // INFO("--------------------------------------------------------------\n");
109
-      // INFO("Got call control start ltag '%s' start_ts %i.%i\n",
110
-      // 	   args.get(0).asCStr(), args[2][0].asInt(), args[2][1].asInt());
111
-      // INFO("---- dumping CC values ----\n");
112
-      // for (AmArg::ValueStruct::const_iterator it =
113
-      // 	     args.get(CC_API_PARAMS_CFGVALUES).begin();
114
-      //               it != args.get(CC_API_PARAMS_CFGVALUES).end(); it++) {
115
-      // 	INFO("    CDR value '%s' = '%s'\n", it->first.c_str(), it->second.asCStr());
116
-      // }
117
-      // INFO("--------------------------------------------------------------\n");
118
-
119
-      // ltag, call profile, timestamps, [[key: val], ...], timer_id
120
-      args.assertArrayFmt("soaui");
121
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
122
-      SBCCallProfile* call_profile =
123
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
124
-
125
-      start(args[CC_API_PARAMS_LTAG].asCStr(),
126
-	    call_profile,
127
-	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_SEC].asInt(),
128
-	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_USEC].asInt(),
129
-	    args[CC_API_PARAMS_CFGVALUES],
130
-	    args[CC_API_PARAMS_TIMERID].asInt(),  ret);
131
-
132
-    } else if(method == "connect"){
133
-      // INFO("--------------------------------------------------------------\n");
134
-      // INFO("Got CDR connect ltag '%s' other_ltag '%s', connect_ts %i.%i\n",
135
-      // 	   args[CC_API_PARAMS_LTAG].asCStr(),
136
-      //           args[CC_API_PARAMS_OTHERID].asCStr(),
137
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
138
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt());
139
-      // INFO("--------------------------------------------------------------\n");
140
-      // ltag, call_profile, other_ltag, connect_ts_sec, connect_ts_usec
141
-      args.assertArrayFmt("soas");
142
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
143
-      SBCCallProfile* call_profile =
144
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
145
-
146
-      connect(args[CC_API_PARAMS_LTAG].asCStr(),
147
-	      call_profile,
148
-	      args[CC_API_PARAMS_OTHERID].asCStr(),
149
-	      args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
150
-	      args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt());
151
-
152
-    } else if(method == "end"){
153
-      // INFO("--------------------------------------------------------------\n");
154
-      // INFO("Got CDR end ltag %s end_ts %i.%i\n",
155
-      // 	   args[CC_API_PARAMS_LTAG].asCStr(),
156
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_SEC].asInt(),
157
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_USEC].asInt());
158
-      // INFO("--------------------------------------------------------------\n");
159
-
160
-      // ltag, call_profile, end_ts_sec, end_ts_usec
161
-      args.assertArrayFmt("soa"); 
162
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
163
-      SBCCallProfile* call_profile =
164
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
165
-
166
-      end(args[CC_API_PARAMS_LTAG].asCStr(),
110
+    start(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
111
+	  args[CC_API_PARAMS_LTAG].asCStr(),
167 112
 	  call_profile,
168 113
 	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_SEC].asInt(),
169 114
 	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_USEC].asInt(),
170
-	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
171
-	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt(),
172
-	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_SEC].asInt(),
173
-	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_USEC].asInt()
174
-	  );
175
-    } else if(method == CC_INTERFACE_MAND_VALUES_METHOD){
176
-
177
-      ret.push("uuid");
178
-
179
-    } else if (method == "getCredit"){
180
-      assertArgCStr(args.get(0));
181
-      bool found;
182
-      ret.push(getCredit(args.get(0).asCStr(), found));
183
-      ret.push(found);
184
-    } else if (method == "subtractCredit"){
185
-      assertArgCStr(args.get(0));
186
-      assertArgInt(args.get(1));
187
-      bool found;
188
-      ret.push(subtractCredit(args.get(0).asCStr(),
189
-			      args.get(1).asInt(),
190
-			      found));
191
-      ret.push(found);
192
-    } else if (method == "_list"){
193
-      ret.push("start");
194
-      ret.push("connect");
195
-      ret.push("end");
196
-
197
-      ret.push("getCredit");
198
-      ret.push("subtractCredit");
199
-    }
200
-    else
201
-	throw AmDynInvoke::NotImplemented(method);
115
+	  args[CC_API_PARAMS_CFGVALUES],
116
+	  args[CC_API_PARAMS_TIMERID].asInt(),  ret);
117
+
118
+  } else if(method == "connect"){
119
+    SBCCallProfile* call_profile =
120
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
121
+
122
+    connect(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
123
+	    args[CC_API_PARAMS_LTAG].asCStr(),
124
+	    call_profile,
125
+	    args[CC_API_PARAMS_OTHERID].asCStr(),
126
+	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
127
+	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt());
128
+
129
+  } else if(method == "end"){
130
+    SBCCallProfile* call_profile =
131
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
132
+
133
+    end(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
134
+	args[CC_API_PARAMS_LTAG].asCStr(),
135
+	call_profile,
136
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_SEC].asInt(),
137
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_USEC].asInt(),
138
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
139
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt(),
140
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_SEC].asInt(),
141
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_USEC].asInt()
142
+	);
143
+  } else if(method == CC_INTERFACE_MAND_VALUES_METHOD){
144
+
145
+    ret.push("uuid");
146
+
147
+  } else if (method == "getCredit"){
148
+    assertArgCStr(args.get(0));
149
+    bool found;
150
+    ret.push(getCredit(args.get(0).asCStr(), found));
151
+    ret.push(found);
152
+  } else if (method == "subtractCredit"){
153
+    assertArgCStr(args.get(0));
154
+    assertArgInt(args.get(1));
155
+    bool found;
156
+    ret.push(subtractCredit(args.get(0).asCStr(),
157
+			    args.get(1).asInt(),
158
+			    found));
159
+    ret.push(found);
160
+  } else if (method == "_list"){
161
+    ret.push("start");
162
+    ret.push("connect");
163
+    ret.push("end");
164
+
165
+    ret.push("getCredit");
166
+    ret.push("subtractCredit");
167
+  }
168
+  else
169
+    throw AmDynInvoke::NotImplemented(method);
202 170
 }
203 171
 
204
-void PrepaidXMLRPC::start(const string& ltag, SBCCallProfile* call_profile,
205
-		       int start_ts_sec, int start_ts_usec,
206
-		       const AmArg& values, int timer_id, AmArg& res) {
172
+void PrepaidXMLRPC::start(const string& cc_name, const string& ltag,
173
+			  SBCCallProfile* call_profile,
174
+			  int start_ts_sec, int start_ts_usec,
175
+			  const AmArg& values, int timer_id, AmArg& res) {
207 176
 
208 177
   if (!call_profile) return;
209 178
 
... ...
@@ -221,7 +190,7 @@ void PrepaidXMLRPC::start(const string& ltag, SBCCallProfile* call_profile,
221 190
 
222 191
   string uuid = values["uuid"].asCStr();
223 192
 
224
-  call_profile->cc_vars[SBCVAR_PREPAID_XMLRPC_UUID] = uuid;
193
+  call_profile->cc_vars[cc_name+"::"+SBCVAR_PREPAID_XMLRPC_UUID] = uuid;
225 194
 
226 195
   bool found;
227 196
   int credit = getCredit(uuid, found);
... ...
@@ -246,21 +215,23 @@ void PrepaidXMLRPC::start(const string& ltag, SBCCallProfile* call_profile,
246 215
   res_cmd[SBC_CC_TIMER_TIMEOUT] = credit;
247 216
 }
248 217
 
249
-void PrepaidXMLRPC::connect(const string& ltag, SBCCallProfile* call_profile,
250
-		      const string& other_tag,
251
-		      int connect_ts_sec, int connect_ts_usec) {
218
+void PrepaidXMLRPC::connect(const string& cc_name,
219
+			    const string& ltag, SBCCallProfile* call_profile,
220
+			    const string& other_tag,
221
+			    int connect_ts_sec, int connect_ts_usec) {
252 222
   // DBG("call '%s' gets connected\n", ltag.c_str());
253 223
 }
254 224
 
255
-void PrepaidXMLRPC::end(const string& ltag, SBCCallProfile* call_profile,
256
-		  int start_ts_sec, int start_ts_usec,
257
-		  int connect_ts_sec, int connect_ts_usec,
258
-		  int end_ts_sec, int end_ts_usec) {
225
+void PrepaidXMLRPC::end(const string& cc_name, const string& ltag,
226
+			SBCCallProfile* call_profile,
227
+			int start_ts_sec, int start_ts_usec,
228
+			int connect_ts_sec, int connect_ts_usec,
229
+			int end_ts_sec, int end_ts_usec) {
259 230
 
260 231
   if (!call_profile) return;
261 232
 
262 233
   // get uuid
263
-  SBCVarMapIteratorT vars_it = call_profile->cc_vars.find(SBCVAR_PREPAID_XMLRPC_UUID);
234
+  SBCVarMapIteratorT vars_it = call_profile->cc_vars.find(cc_name+"::"+SBCVAR_PREPAID_XMLRPC_UUID);
264 235
   if (vars_it == call_profile->cc_vars.end() || !isArgCStr(vars_it->second)) {
265 236
     ERROR("internal: could not find UUID for call '%s' - "
266 237
 	  "not accounting (start_ts %i.%i, connect_ts %i.%i, end_ts %i.%i)\n",
... ...
@@ -271,7 +242,7 @@ void PrepaidXMLRPC::end(const string& ltag, SBCCallProfile* call_profile,
271 242
   }
272 243
 
273 244
   string uuid = vars_it->second.asCStr();
274
-  call_profile->cc_vars.erase(SBCVAR_PREPAID_XMLRPC_UUID);
245
+  call_profile->cc_vars.erase(cc_name+"::"+SBCVAR_PREPAID_XMLRPC_UUID);
275 246
 
276 247
   if (!connect_ts_sec || !end_ts_sec) {
277 248
     DBG("call not connected - uuid '%s' ltag '%s'\n", uuid.c_str(), ltag.c_str());
... ...
@@ -58,13 +58,13 @@ class PrepaidXMLRPC : public AmDynInvoke
58 58
   int setCredit(string pin, int amount);
59 59
 
60 60
 
61
-  void start(const string& ltag, SBCCallProfile* call_profile,
61
+  void start(const string& cc_name, const string& ltag, SBCCallProfile* call_profile,
62 62
 	     int start_ts_sec, int start_ts_usec, const AmArg& values,
63 63
 	     int timer_id, AmArg& res);
64
-  void connect(const string& ltag, SBCCallProfile* call_profile,
64
+  void connect(const string& cc_name, const string& ltag, SBCCallProfile* call_profile,
65 65
 	       const string& other_ltag,
66 66
 	       int connect_ts_sec, int connect_ts_usec);
67
-  void end(const string& ltag, SBCCallProfile* call_profile,
67
+  void end(const string& cc_name, const string& ltag, SBCCallProfile* call_profile,
68 68
 	   int start_ts_sec, int start_ts_usec,
69 69
 	   int connect_ts_sec, int connect_ts_usec,
70 70
 	   int end_ts_sec, int end_ts_usec);
... ...
@@ -105,9 +105,6 @@ void SyslogCDR::invoke(const string& method, const AmArg& args, AmArg& ret)
105 105
   // DBG("SyslogCDR: %s(%s)\n", method.c_str(), AmArg::print(args).c_str());
106 106
 
107 107
     if(method == "start"){
108
-
109
-      // ltag, call profile, timestamps, [[key: val], ...], timer_id
110
-      args.assertArrayFmt("soaui");
111 108
       SBCCallProfile* call_profile =
112 109
 	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
113 110
 
... ...
@@ -117,9 +114,6 @@ void SyslogCDR::invoke(const string& method, const AmArg& args, AmArg& ret)
117 114
     } else if(method == "connect"){
118 115
       // no action needed
119 116
     } else if(method == "end"){
120
-      // ltag, call_profile, timestamps
121
-      args.assertArrayFmt("soa");
122
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
123 117
       SBCCallProfile* call_profile =
124 118
 	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
125 119
 
... ...
@@ -90,82 +90,87 @@ void CCTemplate::invoke(const string& method, const AmArg& args, AmArg& ret)
90 90
 {
91 91
   DBG("CCTemplate: %s(%s)\n", method.c_str(), AmArg::print(args).c_str());
92 92
 
93
-    if(method == "start"){
94
-
95
-
96
-      // INFO("--------------------------------------------------------------\n");
97
-      // INFO("Got call control start ltag '%s' start_ts %i.%i\n",
98
-      // 	   args.get(0).asCStr(), args[2][0].asInt(), args[2][1].asInt());
99
-      // INFO("---- dumping CC values ----\n");
100
-      // for (AmArg::ValueStruct::const_iterator it =
101
-      // 	     args.get(CC_API_PARAMS_CFGVALUES).begin();
102
-      //               it != args.get(CC_API_PARAMS_CFGVALUES).end(); it++) {
103
-      // 	INFO("    CDR value '%s' = '%s'\n", it->first.c_str(), it->second.asCStr());
104
-      // }
105
-      // INFO("--------------------------------------------------------------\n");
106
-
107
-      // ltag, call profile, timestamps, [[key: val], ...], timer_id
108
-      args.assertArrayFmt("soaui");
109
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
110
-      SBCCallProfile* call_profile =
111
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
112
-
113
-      start(args[CC_API_PARAMS_LTAG].asCStr(),
93
+  if(method == "start"){
94
+    // INFO("--------------------------------------------------------------\n");
95
+    // INFO("Got call control start ltag '%s' start_ts %i.%i\n",
96
+    // 	   args.get(0).asCStr(), args[2][0].asInt(), args[2][1].asInt());
97
+    // INFO("---- dumping CC values ----\n");
98
+    // for (AmArg::ValueStruct::const_iterator it =
99
+    // 	     args.get(CC_API_PARAMS_CFGVALUES).begin();
100
+    //               it != args.get(CC_API_PARAMS_CFGVALUES).end(); it++) {
101
+    // 	INFO("    CDR value '%s' = '%s'\n", it->first.c_str(), it->second.asCStr());
102
+    // }
103
+    // INFO("--------------------------------------------------------------\n");
104
+
105
+    // cc_name, ltag, call profile, timestamps, [[key: val], ...], timer_id
106
+    //args.assertArrayFmt("ssoaui");
107
+    //args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
108
+
109
+    SBCCallProfile* call_profile =
110
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
111
+
112
+    start(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
113
+	  args[CC_API_PARAMS_LTAG].asCStr(),
114
+	  call_profile,
115
+	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_SEC].asInt(),
116
+	  args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_USEC].asInt(),
117
+	  args[CC_API_PARAMS_CFGVALUES],
118
+	  args[CC_API_PARAMS_TIMERID].asInt(),  ret);
119
+
120
+  } else if(method == "connect"){
121
+    // INFO("--------------------------------------------------------------\n");
122
+    // INFO("Got CDR connect ltag '%s' other_ltag '%s', connect_ts %i.%i\n",
123
+    // 	   args[CC_API_PARAMS_LTAG].asCStr(),
124
+    //           args[CC_API_PARAMS_OTHERID].asCStr(),
125
+    //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
126
+    //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt());
127
+    // INFO("--------------------------------------------------------------\n");
128
+    // cc_name, ltag, call_profile, other_ltag, connect_ts_sec, connect_ts_usec
129
+    // args.assertArrayFmt("ssoas");
130
+    // args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
131
+
132
+    SBCCallProfile* call_profile =
133
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
134
+
135
+    connect(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
136
+	    args[CC_API_PARAMS_LTAG].asCStr(),
114 137
 	    call_profile,
115
-	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_SEC].asInt(),
116
-	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_START_USEC].asInt(),
117
-	    args[CC_API_PARAMS_CFGVALUES],
118
-	    args[CC_API_PARAMS_TIMERID].asInt(),  ret);
119
-
120
-    } else if(method == "connect"){
121
-      // INFO("--------------------------------------------------------------\n");
122
-      // INFO("Got CDR connect ltag '%s' other_ltag '%s', connect_ts %i.%i\n",
123
-      // 	   args[CC_API_PARAMS_LTAG].asCStr(),
124
-      //           args[CC_API_PARAMS_OTHERID].asCStr(),
125
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
126
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt());
127
-      // INFO("--------------------------------------------------------------\n");
128
-      // ltag, call_profile, other_ltag, connect_ts_sec, connect_ts_usec
129
-      args.assertArrayFmt("soas");
130
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
131
-      SBCCallProfile* call_profile =
132
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
133
-
134
-      connect(args[CC_API_PARAMS_LTAG].asCStr(),
135
-	      call_profile,
136
-	      args[CC_API_PARAMS_OTHERID].asCStr(),
137
-	      args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
138
-	      args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt());
139
-
140
-    } else if(method == "end"){
141
-      // INFO("--------------------------------------------------------------\n");
142
-      // INFO("Got CDR end ltag %s end_ts %i.%i\n",
143
-      // 	   args[CC_API_PARAMS_LTAG].asCStr(),
144
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_SEC].asInt(),
145
-      //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_USEC].asInt());
146
-      // INFO("--------------------------------------------------------------\n");
147
-
148
-      // ltag, call_profile, end_ts_sec, end_ts_usec
149
-      args.assertArrayFmt("soa"); 
150
-      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
151
-      SBCCallProfile* call_profile =
152
-	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
153
-
154
-      end(args[CC_API_PARAMS_LTAG].asCStr(),
155
-	      call_profile,
156
-	      args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_SEC].asInt(),
157
-	      args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_USEC].asInt()
158
-	      );
159
-    } else if(method == "_list"){
160
-      ret.push("start");
161
-      ret.push("connect");
162
-      ret.push("end");
163
-    }
164
-    else
165
-	throw AmDynInvoke::NotImplemented(method);
138
+	    args[CC_API_PARAMS_OTHERID].asCStr(),
139
+	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_SEC].asInt(),
140
+	    args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_CONNECT_USEC].asInt());
141
+
142
+  } else if(method == "end"){
143
+    // INFO("--------------------------------------------------------------\n");
144
+    // INFO("Got CDR end ltag %s end_ts %i.%i\n",
145
+    // 	   args[CC_API_PARAMS_LTAG].asCStr(),
146
+    //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_SEC].asInt(),
147
+    //           args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_USEC].asInt());
148
+    // INFO("--------------------------------------------------------------\n");
149
+
150
+    // cc_name, ltag, call_profile, end_ts_sec, end_ts_usec
151
+    // args.assertArrayFmt("ssoa"); 
152
+    // args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
153
+
154
+    SBCCallProfile* call_profile =
155
+      dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
156
+
157
+    end(args[CC_API_PARAMS_CC_NAMESPACE].asCStr(),
158
+	args[CC_API_PARAMS_LTAG].asCStr(),
159
+	call_profile,
160
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_SEC].asInt(),
161
+	args[CC_API_PARAMS_TIMESTAMPS][CC_API_TS_END_USEC].asInt()
162
+	);
163
+  } else if(method == "_list"){
164
+    ret.push("start");
165
+    ret.push("connect");
166
+    ret.push("end");
167
+  }
168
+  else
169
+    throw AmDynInvoke::NotImplemented(method);
166 170
 }
167 171
 
168
-void CCTemplate::start(const string& ltag, SBCCallProfile* call_profile,
172
+void CCTemplate::start(const string& cc_name, const string& ltag,
173
+		       SBCCallProfile* call_profile,
169 174
 		       int start_ts_sec, int start_ts_usec,
170 175
 		       const AmArg& values, int timer_id, AmArg& res) {
171 176
   // start code here
... ...
@@ -185,14 +190,16 @@ void CCTemplate::start(const string& ltag, SBCCallProfile* call_profile,
185 190
   // res_cmd[SBC_CC_TIMER_TIMEOUT] = 5;
186 191
 }
187 192
 
188
-void CCTemplate::connect(const string& ltag, SBCCallProfile* call_profile,
193
+void CCTemplate::connect(const string& cc_name, const string& ltag,
194
+			 SBCCallProfile* call_profile,
189 195
 			 const string& other_tag,
190 196
 			 int connect_ts_sec, int connect_ts_usec) {
191 197
   // connect code here
192 198
 
193 199
 }
194 200
 
195
-void CCTemplate::end(const string& ltag, SBCCallProfile* call_profile,
201
+void CCTemplate::end(const string& cc_name, const string& ltag,
202
+		     SBCCallProfile* call_profile,
196 203
 		     int end_ts_sec, int end_ts_usec) {
197 204
   // end code here
198 205
 
... ...
@@ -37,13 +37,13 @@ class CCTemplate : public AmDynInvoke
37 37
 {
38 38
   static CCTemplate* _instance;
39 39
 
40
-  void start(const string& ltag, SBCCallProfile* call_profile,
40
+  void start(const string& cc_name, const string& ltag, SBCCallProfile* call_profile,
41 41
 	     int start_ts_sec, int start_ts_usec, const AmArg& values,
42 42
 	     int timer_id, AmArg& res);
43
-  void connect(const string& ltag, SBCCallProfile* call_profile,
43
+  void connect(const string& cc_name, const string& ltag, SBCCallProfile* call_profile,
44 44
 	       const string& other_ltag,
45 45
 	       int connect_ts_sec, int connect_ts_usec);
46
-  void end(const string& ltag, SBCCallProfile* call_profile,
46
+  void end(const string& cc_name, const string& ltag, SBCCallProfile* call_profile,
47 47
 	   int end_ts_sec, int end_ts_usec);
48 48
 
49 49
  public:
... ...
@@ -4,14 +4,15 @@
4 4
 #define CC_INTERFACE_MAND_VALUES_METHOD "getMandatoryValues"
5 5
 
6 6
 
7
-#define CC_API_PARAMS_LTAG              0
8
-#define CC_API_PARAMS_CALL_PROFILE      1
9
-#define CC_API_PARAMS_TIMESTAMPS        2
7
+#define CC_API_PARAMS_CC_NAMESPACE      0
8
+#define CC_API_PARAMS_LTAG              1
9
+#define CC_API_PARAMS_CALL_PROFILE      2
10
+#define CC_API_PARAMS_TIMESTAMPS        3
10 11
 
11
-#define CC_API_PARAMS_CFGVALUES         3
12
-#define CC_API_PARAMS_TIMERID           4
12
+#define CC_API_PARAMS_CFGVALUES         4
13
+#define CC_API_PARAMS_TIMERID           5
13 14
 
14
-#define CC_API_PARAMS_OTHERID           3
15
+#define CC_API_PARAMS_OTHERID           4
15 16
 
16 17
 #define CC_API_TS_START_SEC             0
17 18
 #define CC_API_TS_START_USEC            1
... ...
@@ -64,7 +64,9 @@ The CC modules must implement a DI API, which must implement at least the functi
64 64
 
65 65
 
66 66
   function: start
67
-  Parameters: string                  ltag             local tag (ID) of the call (A leg)
67
+  Parameters: string                  cc_namespace     name of call control section
68
+                                                       (as configured, e.g. variable namespace to use)
69
+              string                  ltag             local tag (ID) of the call (A leg)
68 70
               SBCCallProfile Object   call_profile     used call profile instance
69 71
               Array of int            timestamps       start/connect/end timestamp
70 72
               ValueStruct             values           configured values
... ...
@@ -90,14 +92,18 @@ The CC modules must implement a DI API, which must implement at least the functi
90 92
                   Parameters: int    timeout
91 93
 
92 94
   function: connect
93
-  Parameters: string                  ltag             local tag (ID) of the call (A leg)
95
+  Parameters: string                  cc_namespace     name of call control section
96
+                                                       (as configured, e.g. variable namespace to use)
97
+              string                  ltag             local tag (ID) of the call (A leg)
94 98
               SBCCallProfile Object   call_profile     used call profile instance
95 99
               Array of int            timestamps       start/connect/end timestamp
96 100
               string                  other ltag       local tag (ID) of B leg
97 101
 
98 102
 
99 103
   function: end
100
-  Parameters: string                  ltag             local tag (ID) of the call (A leg)
104
+  Parameters: string                  cc_namespace     name of call control section
105
+                                                       (as configured, e.g. variable namespace to use)
106
+              string                  ltag             local tag (ID) of the call (A leg)
101 107
               SBCCallProfile Object   call_profile     used call profile instance
102 108
               Array of int            timestamps       start/connect/end timestamp
103 109
 
... ...
@@ -134,7 +140,9 @@ Synopsis:
134 140
   removing a variable:
135 141
     call_profile->cc_vars.erase("mycc::myvar");
136 142
 
137
-CC variables may be prefixed by the CC module name as name space (e.g. cc_name::var_name).
143
+If several invocations of the same call control module should be independent from each other,
144
+CC variables may be prefixed by the CC namespace
145
+(e.g. args[CC_API_PARAMS_CC_NAMESPACE + "::" + var_name).
138 146
 
139 147
 
140 148
 Verifying correct configuration