Browse code

sbc: cc: modified API to have all timestamps in all functions

Stefan Sayer authored on 29/09/2011 12:22:30
Showing 7 changed files
... ...
@@ -1285,15 +1285,20 @@ bool SBCDialog::CCStart(const AmSipRequest& req) {
1285 1285
     AmArg di_args,ret;
1286 1286
     di_args.push(getLocalTag());
1287 1287
     di_args.push((ArgObject*)&call_profile);
1288
-    di_args.push((int)prepaid_starttime.tv_sec);
1289
-    di_args.push((int)prepaid_starttime.tv_usec);
1290 1288
     di_args.push(AmArg());
1291
-    AmArg& vals = di_args.get(4);
1289
+    di_args.back().push((int)prepaid_starttime.tv_sec);
1290
+    di_args.back().push((int)prepaid_starttime.tv_usec);
1291
+    for (int i=0;i<4;i++)
1292
+      di_args.back().push((int)0);
1293
+
1294
+    di_args.push(AmArg());
1295
+    AmArg& vals = di_args.back();
1292 1296
     vals.assertStruct();
1293 1297
     for (map<string, string>::iterator it = cc_if.cc_values.begin();
1294 1298
 	 it != cc_if.cc_values.end(); it++) {
1295 1299
       vals[it->first] = it->second;
1296 1300
     }
1301
+
1297 1302
     di_args.push(cc_timer_id); // current timer ID
1298 1303
 
1299 1304
     (*cc_mod)->invoke("start", di_args, ret);
... ...
@@ -1383,10 +1388,16 @@ void SBCDialog::CCConnect(const AmSipReply& reply) {
1383 1388
 
1384 1389
     AmArg di_args,ret;
1385 1390
     di_args.push(getLocalTag());                 // call ltag
1386
-    di_args.push((ArgObject*)&call_profile);
1391
+    di_args.push((ArgObject*)&call_profile);     // call profile
1392
+    di_args.push(AmArg());                       // timestamps
1393
+    di_args.back().push((int)prepaid_starttime.tv_sec);
1394
+    di_args.back().push((int)prepaid_starttime.tv_usec);
1395
+    di_args.back().push((int)prepaid_acc_start.tv_sec);
1396
+    di_args.back().push((int)prepaid_acc_start.tv_usec);
1397
+    for (int i=0;i<2;i++)
1398
+      di_args.back().push((int)0);
1387 1399
     di_args.push(other_id);                      // other leg ltag
1388
-    di_args.push((int)prepaid_acc_start.tv_sec);
1389
-    di_args.push((int)prepaid_acc_start.tv_usec);
1400
+
1390 1401
     (*cc_mod)->invoke("connect", di_args, ret);
1391 1402
 
1392 1403
     cc_mod++;
... ...
@@ -1403,8 +1414,13 @@ void SBCDialog::CCEnd() {
1403 1414
     AmArg di_args,ret;
1404 1415
     di_args.push(getLocalTag());                 // call ltag
1405 1416
     di_args.push((ArgObject*)&call_profile);
1406
-    di_args.push((int)prepaid_acc_end.tv_sec);
1407
-    di_args.push((int)prepaid_acc_end.tv_usec);
1417
+    di_args.push(AmArg());                       // timestamps
1418
+    di_args.back().push((int)prepaid_starttime.tv_sec);
1419
+    di_args.back().push((int)prepaid_starttime.tv_usec);
1420
+    di_args.back().push((int)prepaid_acc_start.tv_sec);
1421
+    di_args.back().push((int)prepaid_acc_start.tv_usec);
1422
+    di_args.back().push((int)prepaid_acc_end.tv_sec);
1423
+    di_args.back().push((int)prepaid_acc_end.tv_usec);
1408 1424
     (*cc_mod)->invoke("end", di_args, ret);
1409 1425
 
1410 1426
     cc_mod++;
... ...
@@ -73,26 +73,27 @@ void CCParallelCalls::invoke(const string& method, const AmArg& args, AmArg& ret
73 73
 
74 74
     if(method == "start"){
75 75
 
76
-      // ltag, call profile, start_ts_sec, start_ts_usec, [[key: val], ...], timer_id
77
-      args.assertArrayFmt("soiiui");
78
-      SBCCallProfile* call_profile = dynamic_cast<SBCCallProfile*>(args[1].asObject());
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());
79 80
 
80
-      start(args[0].asCStr(), call_profile, args[2].asInt(), args[3].asInt(), args[4],
81
-	    args[5].asInt(),  ret);
81
+      start(args[CC_API_PARAMS_LTAG].asCStr(), call_profile,
82
+	    args[CC_API_PARAMS_CFGVALUES], ret);
82 83
 
83 84
     } else if(method == "connect"){
84
-      // ltag, call_profile, other_ltag, connect_ts_sec, connect_ts_usec
85
-      args.assertArrayFmt("sosii");
86
-      SBCCallProfile* call_profile = dynamic_cast<SBCCallProfile*>(args[1].asObject());
85
+      // no action
87 86
 
88
-      connect(args.get(0).asCStr(), call_profile, args.get(2).asCStr(),
89
-	      args.get(3).asInt(), args.get(4).asInt());
90 87
     } else if(method == "end"){
88
+
91 89
       // ltag, call_profile, end_ts_sec, end_ts_usec
92
-      args.assertArrayFmt("soii"); 
93
-      SBCCallProfile* call_profile = dynamic_cast<SBCCallProfile*>(args[1].asObject());
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);
94 96
 
95
-      end(args.get(0).asCStr(), call_profile, args.get(2).asInt(), args.get(3).asInt());
96 97
     } else if(method == CC_INTERFACE_MAND_VALUES_METHOD){
97 98
       ret.push("uuid");
98 99
     } else if(method == "_list"){
... ...
@@ -105,8 +106,7 @@ void CCParallelCalls::invoke(const string& method, const AmArg& args, AmArg& ret
105 106
 }
106 107
 
107 108
 void CCParallelCalls::start(const string& ltag, SBCCallProfile* call_profile,
108
-			    int start_ts_sec, int start_ts_usec,
109
-			    const AmArg& values, int timer_id, AmArg& res) {
109
+			    const AmArg& values, AmArg& res) {
110 110
   if (!call_profile) return;
111 111
 
112 112
   if (!values.hasMember("uuid") || !isArgCStr(values["uuid"]) ||
... ...
@@ -171,14 +171,7 @@ void CCParallelCalls::start(const string& ltag, SBCCallProfile* call_profile,
171 171
 
172 172
 }
173 173
 
174
-void CCParallelCalls::connect(const string& ltag, SBCCallProfile* call_profile,
175
-			      const string& other_tag,
176
-			      int connect_ts_sec, int connect_ts_usec) {
177
-  if (!call_profile) return;
178
-}
179
-
180
-void CCParallelCalls::end(const string& ltag, SBCCallProfile* call_profile,
181
-			  int end_ts_sec, int end_ts_usec) {
174
+void CCParallelCalls::end(const string& ltag, SBCCallProfile* call_profile) {
182 175
   if (!call_profile) return;
183 176
 
184 177
   SBCVarMapIteratorT vars_it = call_profile->cc_vars.find(SBCVAR_PARALLEL_CALLS_UUID);
... ...
@@ -48,13 +48,8 @@ class CCParallelCalls : public AmDynInvoke
48 48
   static CCParallelCalls* _instance;
49 49
 
50 50
   void start(const string& ltag, SBCCallProfile* call_profile,
51
-	     int start_ts_sec, int start_ts_usec, const AmArg& values,
52
-	     int timer_id, AmArg& res);
53
-  void connect(const string& ltag, SBCCallProfile* call_profile,
54
-	       const string& other_ltag,
55
-	       int connect_ts_sec, int connect_ts_usec);
56
-  void end(const string& ltag, SBCCallProfile* call_profile,
57
-	   int end_ts_sec, int end_ts_usec);
51
+	     const AmArg& values, AmArg& res);
52
+  void end(const string& ltag, SBCCallProfile* call_profile);
58 53
 
59 54
  public:
60 55
   CCParallelCalls();
... ...
@@ -106,26 +106,32 @@ void SyslogCDR::invoke(const string& method, const AmArg& args, AmArg& ret)
106 106
 
107 107
     if(method == "start"){
108 108
 
109
-      // ltag, call profile, start_ts_sec, start_ts_usec, [[key: val], ...], timer_id
110
-      args.assertArrayFmt("soiiui");
111
-      SBCCallProfile* call_profile = dynamic_cast<SBCCallProfile*>(args[1].asObject());
109
+      // ltag, call profile, timestamps, [[key: val], ...], timer_id
110
+      args.assertArrayFmt("soaui");
111
+      SBCCallProfile* call_profile =
112
+	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
112 113
 
113
-      start(args[0].asCStr(), call_profile, args[2].asInt(), args[3].asInt(), args[4],
114
-	    args[5].asInt(),  ret);
114
+      start(args[CC_API_PARAMS_LTAG].asCStr(),
115
+	    call_profile, args[CC_API_PARAMS_CFGVALUES]);
115 116
 
116 117
     } else if(method == "connect"){
117
-      // ltag, call_profile, other_ltag, connect_ts_sec, connect_ts_usec
118
-      args.assertArrayFmt("sosii");
119
-      SBCCallProfile* call_profile = dynamic_cast<SBCCallProfile*>(args[1].asObject());
120
-
121
-      connect(args.get(0).asCStr(), call_profile, args.get(2).asCStr(),
122
-	      args.get(3).asInt(), args.get(4).asInt());
118
+      // no action needed
123 119
     } else if(method == "end"){
124
-      // ltag, call_profile, end_ts_sec, end_ts_usec
125
-      args.assertArrayFmt("soii"); 
126
-      SBCCallProfile* call_profile = dynamic_cast<SBCCallProfile*>(args[1].asObject());
127
-
128
-      end(args.get(0).asCStr(), call_profile, args.get(2).asInt(), args.get(3).asInt());
120
+      // ltag, call_profile, timestamps
121
+      args.assertArrayFmt("soa");
122
+      args[CC_API_PARAMS_TIMESTAMPS].assertArrayFmt("iiiiii");
123
+      SBCCallProfile* call_profile =
124
+	dynamic_cast<SBCCallProfile*>(args[CC_API_PARAMS_CALL_PROFILE].asObject());
125
+
126
+      end(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
+	  );
129 135
     } else if(method == CC_INTERFACE_MAND_VALUES_METHOD){
130 136
       // ret.push("Call-ID");
131 137
       // ret.push("From-tag");
... ...
@@ -149,69 +155,20 @@ string timeString(time_t tv_sec) {
149 155
 }
150 156
 
151 157
 void SyslogCDR::start(const string& ltag, SBCCallProfile* call_profile,
152
-		      int start_ts_sec, int start_ts_usec,
153
-		      const AmArg& values, int timer_id, AmArg& res) {
154
-  if (!call_profile) return;
155
-  /*
156
-// #define CHECK_PARAMETER(pname)						\
157
-//   if (!values.hasMember(pname) || !isArgCStr(values[pname]) ||		\
158
-//       !strlen(values[pname].asCStr())) {				\
159
-//     ERROR("configuration error: " pname " missing for SyslogCDR call control!\n"); \
160
-//     res.push(AmArg());							\
161
-//     AmArg& res_cmd = res[0];						\
162
-//     res_cmd[SBC_CC_ACTION] = SBC_CC_REFUSE_ACTION;			\
163
-//     res_cmd[SBC_CC_REFUSE_CODE] = 500;					\
164
-//     res_cmd[SBC_CC_REFUSE_REASON] = SIP_REPLY_SERVER_INTERNAL_ERROR;	\
165
-//     return;								\
166
-//   }
167
-//   CHECK_PARAMETER("Call-ID");
168
-//   CHECK_PARAMETER("From-tag");
169
-// #undef CHECK_PARAMETER
170
-*/
171
-
172
-  call_profile->cc_vars["cdr::t::start"] = start_ts_sec;
173
-  call_profile->cc_vars["cdr::t::start_us"] = start_ts_usec;
174
-  call_profile->cc_vars["cdr::v"] = values;
175
-}
176
-
177
-
178
-void SyslogCDR::connect(const string& ltag, SBCCallProfile* call_profile,
179
-			const string& other_tag,
180
-			int connect_ts_sec, int connect_ts_usec) {
158
+		      const AmArg& values) {
181 159
   if (!call_profile) return;
182 160
 
183
-  call_profile->cc_vars["cdr::t::connect"] = connect_ts_sec;
184
-  call_profile->cc_vars["cdr::t::connect_us"] = connect_ts_usec;
161
+  call_profile->cc_vars["cdr::v"] = values;
185 162
 }
186 163
 
187
-
188 164
 void SyslogCDR::end(const string& ltag, SBCCallProfile* call_profile,
165
+		    int start_ts_sec, int start_ts_usec,
166
+		    int connect_ts_sec, int connect_ts_usec,
189 167
 		    int end_ts_sec, int end_ts_usec) {
190 168
   if (!call_profile) return;
191 169
 
192
-  int start_ts_sec=0, start_ts_usec=0, connect_ts_sec=0, connect_ts_usec=0;
193
-
194 170
   static const int log2syslog_level[] = { LOG_ERR, LOG_WARNING, LOG_INFO, LOG_DEBUG };
195 171
 
196
-  // for (SBCVarMapIteratorT vars_it = call_profile->cc_vars.begin(); vars_it != call_profile->cc_vars.end(); vars_it++) {
197
-  //   ERROR ("cc_vars '%s' = '%s'\n", vars_it->first.c_str(), AmArg::print(vars_it->second).c_str());
198
-  // }
199
-
200
-
201
-#define GET_INT_VAR(vname, vdst)					\
202
-  {									\
203
-    SBCVarMapIteratorT vars_it = call_profile->cc_vars.find(vname);	\
204
-    if (vars_it != call_profile->cc_vars.end() && isArgInt(vars_it->second)) { \
205
-      vdst = vars_it->second.asInt();					\
206
-    }									\
207
-  }
208
-
209
-  GET_INT_VAR("cdr::t::start", start_ts_sec);
210
-  GET_INT_VAR("cdr::t::start_us", start_ts_usec);
211
-  GET_INT_VAR("cdr::t::connect", connect_ts_sec);
212
-  GET_INT_VAR("cdr::t::connect_us", connect_ts_usec);
213
-#undef GET_INT_VAR
214
-
215 172
   struct timeval start;
216 173
   start.tv_sec = connect_ts_sec;
217 174
   start.tv_usec = connect_ts_usec;
... ...
@@ -77,12 +77,10 @@ class SyslogCDR : public AmDynInvoke
77 77
   AmMutex cdrs_mut;
78 78
 
79 79
   void start(const string& ltag, SBCCallProfile* call_profile,
80
-	     int start_ts_sec, int start_ts_usec, const AmArg& values,
81
-	     int timer_id, AmArg& res);
82
-  void connect(const string& ltag, SBCCallProfile* call_profile,
83
-	       const string& other_ltag,
84
-	       int connect_ts_sec, int connect_ts_usec);
80
+	     const AmArg& values);
85 81
   void end(const string& ltag, SBCCallProfile* call_profile,
82
+	   int start_ts_sec, int start_ts_usec,
83
+	   int connect_ts_sec, int connect_ts_usec,
86 84
 	   int end_ts_sec, int end_ts_usec);
87 85
 
88 86
  public:
... ...
@@ -53,7 +53,7 @@ public:
53 53
     }
54 54
 };
55 55
 
56
-EXPORT_PLUGIN_CLASS_FACTORY(CCTemplateFactory,"cc_template");
56
+EXPORT_PLUGIN_CLASS_FACTORY(CCTemplateFactory, MOD_NAME);
57 57
 
58 58
 CCTemplate* CCTemplate::_instance=0;
59 59
 
... ...
@@ -95,44 +95,67 @@ void CCTemplate::invoke(const string& method, const AmArg& args, AmArg& ret)
95 95
 
96 96
       // INFO("--------------------------------------------------------------\n");
97 97
       // INFO("Got call control start ltag '%s' start_ts %i.%i\n",
98
-      // 	   args.get(0).asCStr(), args.get(2).asInt(), args.get(3).asInt());
98
+      // 	   args.get(0).asCStr(), args[2][0].asInt(), args[2][1].asInt());
99 99
       // INFO("---- dumping CC values ----\n");
100 100
       // for (AmArg::ValueStruct::const_iterator it =
101
-      // 	     args.get(4).begin(); it != args.get(4).end(); it++) {
101
+      // 	     args.get(CC_API_PARAMS_CFGVALUES).begin();
102
+      //               it != args.get(CC_API_PARAMS_CFGVALUES).end(); it++) {
102 103
       // 	INFO("    CDR value '%s' = '%s'\n", it->first.c_str(), it->second.asCStr());
103 104
       // }
104 105
       // INFO("--------------------------------------------------------------\n");
105 106
 
106
-      // ltag, call profile, start_ts_sec, start_ts_usec, [[key: val], ...], timer_id
107
-      args.assertArrayFmt("soiiui");
108
-      SBCCallProfile* call_profile = dynamic_cast<SBCCallProfile*>(args[1].asObject());
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());
109 112
 
110
-      start(args[0].asCStr(), call_profile, args[2].asInt(), args[3].asInt(), args[4],
111
-	    args[5].asInt(),  ret);
113
+      start(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);
112 119
 
113 120
     } else if(method == "connect"){
114 121
       // INFO("--------------------------------------------------------------\n");
115 122
       // INFO("Got CDR connect ltag '%s' other_ltag '%s', connect_ts %i.%i\n",
116
-      // 	   args.get(0).asCStr(), args.get(2).asCStr(), args.get(3).asInt(),
117
-      // 	   args.get(4).asInt());
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());
118 127
       // INFO("--------------------------------------------------------------\n");
119 128
       // ltag, call_profile, other_ltag, connect_ts_sec, connect_ts_usec
120
-      args.assertArrayFmt("sosii");
121
-      SBCCallProfile* call_profile = dynamic_cast<SBCCallProfile*>(args[1].asObject());
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());
122 139
 
123
-      connect(args.get(0).asCStr(), call_profile, args.get(2).asCStr(),
124
-	      args.get(3).asInt(), args.get(4).asInt());
125 140
     } else if(method == "end"){
126 141
       // INFO("--------------------------------------------------------------\n");
127 142
       // INFO("Got CDR end ltag %s end_ts %i.%i\n",
128
-      // 	   args.get(0).asCStr(), args.get(2).Int(), args.get(3).asInt());
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());
129 146
       // INFO("--------------------------------------------------------------\n");
130 147
 
131 148
       // ltag, call_profile, end_ts_sec, end_ts_usec
132
-      args.assertArrayFmt("soii"); 
133
-      SBCCallProfile* call_profile = dynamic_cast<SBCCallProfile*>(args[1].asObject());
134
-
135
-      end(args.get(0).asCStr(), call_profile, args.get(2).asInt(), args.get(3).asInt());
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
+	      );
136 159
     } else if(method == "_list"){
137 160
       ret.push("start");
138 161
       ret.push("connect");
... ...
@@ -62,13 +62,15 @@ If the call profile is to be modified, SBCCallProfile.h should be included.
62 62
 The CC modules must implement a DI API, which must implement at least the functions "start",
63 63
 "connect", "end".
64 64
 
65
+
65 66
   function: start
66 67
   Parameters: string                  ltag             local tag (ID) of the call (A leg)
67 68
               SBCCallProfile Object   call_profile     used call profile instance
68
-              int                     start_ts_sec     start TS (seconds since epoch)
69
-              int                     start_ts_usec    start TS usec
70
-              ValueStruct             values           configured values (struct of key:string value)
71
-              int                     timer_id         ID of first timer if set with timer action
69
+              Array of int            timestamps       start/connect/end timestamp
70
+              ValueStruct             values           configured values
71
+                                                       (struct of key:string value)
72
+              int                     timer_id         ID of first timer if set with timer
73
+                                                       action
72 74
    
73 75
   Return values
74 76
               Array of actions:
... ...
@@ -83,8 +85,32 @@ The CC modules must implement a DI API, which must implement at least the functi
83 85
                   Parameters: int    code
84 86
                               string reason
85 87
 
86
-               SBC_CC_SET_CALL_TIMER_ACTION             set a timer; the id of the first timer will be timer_id
88
+               SBC_CC_SET_CALL_TIMER_ACTION             set a timer; the id of the first
89
+                                                        timer will be timer_id
87 90
                   Parameters: int    timeout
91
+
92
+  function: connect
93
+  Parameters: string                  ltag             local tag (ID) of the call (A leg)
94
+              SBCCallProfile Object   call_profile     used call profile instance
95
+              Array of int            timestamps       start/connect/end timestamp
96
+              string                  other ltag       local tag (ID) of B leg
97
+
98
+
99
+  function: end
100
+  Parameters: string                  ltag             local tag (ID) of the call (A leg)
101
+              SBCCallProfile Object   call_profile     used call profile instance
102
+              Array of int            timestamps       start/connect/end timestamp
103
+
104
+
105
+  timestamps Array of int
106
+  -----------------------
107
+       0           CC_API_TS_START_SEC                start TS sec (seconds since epoch)
108
+       1           CC_API_TS_START_USEC               start TS usec
109
+       2           CC_API_TS_CONNECT_SEC              connect TS sec (seconds since epoch)
110
+       3           CC_API_TS_CONNECT_USEC             connect TS usec
111
+       4           CC_API_TS_END_SEC                  end TS sec (seconds since epoch)
112
+       5           CC_API_TS_END_USEC                 end TS usec
113
+
88 114
  
89 115
 Storing call related information
90 116
 --------------------------------