Browse code

sbc: add cause as stopCall parameter

Václav Kubart authored on 18/07/2013 11:51:26
Showing 4 changed files
... ...
@@ -296,14 +296,14 @@ void CallLeg::b2bInitial1xx(AmSipReply& reply, bool forward)
296 296
         " other leg ID (%s)\n", getOtherId().c_str());
297 297
     if (setOther(reply.from_tag, initial_sdp_stored && forward)) {
298 298
       updateCallStatus(Ringing, &reply);
299
-      if (forward && relaySipReply(reply) != 0) stopCall();
299
+      if (forward && relaySipReply(reply) != 0) stopCall(StatusChangeCause::InternalError);
300 300
     }
301 301
   }
302 302
   else {
303 303
     if (getOtherId() == reply.from_tag) {
304 304
       // we can relay this reply because it is from the same B leg from which
305 305
       // we already relayed something
306
-      if (forward && relaySipReply(reply) != 0) stopCall();
306
+      if (forward && relaySipReply(reply) != 0) stopCall(StatusChangeCause::InternalError);
307 307
     }
308 308
     else {
309 309
       // in Ringing state but the reply comes from another B leg than
... ...
@@ -342,7 +342,7 @@ void CallLeg::b2bInitial2xx(AmSipReply& reply, bool forward)
342 342
     sendEstablishedReInvite();
343 343
   }
344 344
   else if (relaySipReply(reply) != 0) {
345
-    stopCall();
345
+    stopCall(StatusChangeCause::InternalError);
346 346
     return;
347 347
   }
348 348
   updateCallStatus(Connected, &reply);
... ...
@@ -375,7 +375,7 @@ void CallLeg::b2bInitialErr(AmSipReply& reply, bool forward)
375 375
 
376 376
   // no other B legs, terminate
377 377
   updateCallStatus(Disconnected, &reply);
378
-  stopCall();
378
+  stopCall(&reply);
379 379
 }
380 380
 
381 381
 // was for caller only
... ...
@@ -477,7 +477,7 @@ void CallLeg::onB2BConnect(ConnectLegEvent* co_ev)
477 477
     DBG("sending INVITE failed, relaying back error reply\n");
478 478
     relayError(SIP_METH_INVITE, co_ev->r_cseq, true, res);
479 479
 
480
-    stopCall();
480
+    stopCall(StatusChangeCause::InternalError);
481 481
     return;
482 482
   }
483 483
 
... ...
@@ -559,7 +559,7 @@ void CallLeg::onB2BReconnect(ReconnectLegEvent* ev)
559 559
     DBG("sending re-INVITE failed, relaying back error reply\n");
560 560
     relayError(SIP_METH_INVITE, ev->r_cseq, true, res);
561 561
 
562
-    stopCall();
562
+    stopCall(StatusChangeCause::InternalError);
563 563
     return;
564 564
   }
565 565
 
... ...
@@ -615,7 +615,7 @@ void CallLeg::onB2BReplace(ReplaceLegEvent *e)
615 615
   removeOtherLeg(id);
616 616
 
617 617
   // commit suicide if our last B leg is stolen
618
-  if (other_legs.empty() && getOtherId().empty()) stopCall();
618
+  if (other_legs.empty() && getOtherId().empty()) stopCall(StatusChangeCause::Other /* FIXME? */);
619 619
 }
620 620
 
621 621
 void CallLeg::onB2BReplaceInProgress(ReplaceInProgressEvent *e)
... ...
@@ -817,7 +817,7 @@ void CallLeg::onSipRequest(const AmSipRequest& req)
817 817
     // this is not correct but what is?
818 818
     AmSession::onSipRequest(req);
819 819
     if (req.method == SIP_METH_BYE) {
820
-      stopCall(); // is this needed?
820
+      stopCall(&req); // is this needed?
821 821
     }
822 822
   }
823 823
   else AmB2BSession::onSipRequest(req);
... ...
@@ -870,6 +870,7 @@ void CallLeg::onSipReply(const AmSipRequest& req, const AmSipReply& reply, AmSip
870 870
       updateCallStatus(Connected, &reply);
871 871
     }
872 872
     else if (reply.code >= 300) {
873
+      updateCallStatus(Disconnected, &reply);
873 874
       terminateLeg(); // commit suicide (don't let the master to kill us)
874 875
     }
875 876
   }
... ...
@@ -901,7 +902,7 @@ void CallLeg::onCancel(const AmSipRequest& req)
901 902
       // terminate whole B2B call if the caller receives CANCEL
902 903
       onCallFailed(CallCanceled, NULL);
903 904
       updateCallStatus(Disconnected, StatusChangeCause::Canceled);
904
-      stopCall();
905
+      stopCall(StatusChangeCause::Canceled);
905 906
     }
906 907
     // else { } ... ignore for B leg
907 908
   }
... ...
@@ -1132,7 +1133,8 @@ void CallLeg::clear_other()
1132 1133
   AmB2BSession::clear_other();
1133 1134
 }
1134 1135
 
1135
-void CallLeg::stopCall() {
1136
+void CallLeg::stopCall(const StatusChangeCause &cause) {
1137
+  if (getCallStatus() != Disconnected) updateCallStatus(Disconnected, cause);
1136 1138
   terminateNotConnectedLegs();
1137 1139
   terminateOtherLeg();
1138 1140
   terminateLeg();
... ...
@@ -202,16 +202,19 @@ class CallLeg: public AmB2BSession
202 202
         NoPrack,
203 203
         RtpTimeout,
204 204
         SessionTimeout,
205
-        Unspecified
205
+        InternalError,
206
+        Other
206 207
       } reason;
207 208
 
208 209
       union {
209 210
         const AmSipReply *reply;
210 211
         const AmSipRequest *request;
212
+        const char *desc;
211 213
       } param;
212 214
       StatusChangeCause(const AmSipReply *r): reason(SipReply) { param.reply = r; }
213 215
       StatusChangeCause(const AmSipRequest *r): reason(SipRequest) { param.request = r; }
214
-      StatusChangeCause(): reason(Unspecified) { param.reply = NULL; }
216
+      StatusChangeCause(): reason(Other) { param.desc = NULL; }
217
+      StatusChangeCause(const char *desc): reason(Other) { param.desc = desc; }
215 218
       StatusChangeCause(const Reason r): reason(r) { param.reply = NULL; }
216 219
     };
217 220
 
... ...
@@ -361,7 +364,7 @@ class CallLeg: public AmB2BSession
361 364
 
362 365
     /** Terminate the whole B2B call (if there is no other leg only this one is
363 366
      * stopped). */
364
-    virtual void stopCall();
367
+    virtual void stopCall(const StatusChangeCause &cause);
365 368
 
366 369
 
367 370
     /** Put remote party on hold (may change RTP relay mode!). Note that this
... ...
@@ -639,7 +639,7 @@ void SBCCallLeg::onControlCmd(string& cmd, AmArg& params) {
639 639
     if (a_leg) {
640 640
       // was for caller:
641 641
       DBG("teardown requested from control cmd\n");
642
-      stopCall();
642
+      stopCall("ctrl-cmd");
643 643
       SBCEventLog::instance()->logCallEnd(dlg,"ctrl-cmd",&call_connect_ts);
644 644
       // FIXME: don't we want to relay the controll event as well?
645 645
     }
... ...
@@ -668,7 +668,7 @@ void SBCCallLeg::process(AmEvent* ev) {
668 668
       if (timer_id >= SBC_TIMER_ID_CALL_TIMERS_START &&
669 669
           timer_id <= SBC_TIMER_ID_CALL_TIMERS_END) {
670 670
         DBG("timer %d timeout, stopping call\n", timer_id);
671
-        stopCall();
671
+        stopCall("timer");
672 672
 	SBCEventLog::instance()->logCallEnd(dlg,"timeout",&call_connect_ts);
673 673
         ev->processed = true;
674 674
       }
... ...
@@ -1181,14 +1181,14 @@ void SBCCallLeg::CCConnect(const AmSipReply& reply) {
1181 1181
 	    "module '%s' named '%s', parameters '%s'\n",
1182 1182
 	    cc_if.cc_module.c_str(), cc_if.cc_name.c_str(),
1183 1183
 	    AmArg::print(di_args).c_str());
1184
-      stopCall();
1184
+      stopCall(StatusChangeCause::InternalError);
1185 1185
       return;
1186 1186
     } catch (const AmArg::TypeMismatchException& e) {
1187 1187
       ERROR("TypeMismatchException executing call control interface connect "
1188 1188
 	    "module '%s' named '%s', parameters '%s'\n",
1189 1189
 	    cc_if.cc_module.c_str(), cc_if.cc_name.c_str(),
1190 1190
 	    AmArg::print(di_args).c_str());
1191
-      stopCall();
1191
+      stopCall(StatusChangeCause::InternalError);
1192 1192
       return;
1193 1193
     }
1194 1194
 
... ...
@@ -146,6 +146,9 @@ void SyslogCDR::invoke(const string& method, const AmArg& args, AmArg& ret)
146 146
 }
147 147
 
148 148
 string timeString(time_t tv_sec) {
149
+  static const string empty;
150
+  if (tv_sec == 0) return empty; // better empty than invalid time
151
+
149 152
   char outstr[200];
150 153
   struct tm tmp;
151 154
   if (!localtime_r(&tv_sec, &tmp) || strftime(outstr, sizeof(outstr), "%F %T", &tmp) == 0) {
... ...
@@ -396,7 +399,7 @@ void SyslogCDR::onStateChange(SBCCallLeg *call, const CallLeg::StatusChangeCause
396 399
         cdr["disposition"] = "no PRACK";
397 400
         break;
398 401
 
399
-      case CallLeg::StatusChangeCause::Unspecified:
402
+      case CallLeg::StatusChangeCause::Other:
400 403
           if (s == CallLeg::Connected)
401 404
             cdr["disposition"] = "answered";
402 405
           else
... ...
@@ -411,6 +414,10 @@ void SyslogCDR::onStateChange(SBCCallLeg *call, const CallLeg::StatusChangeCause
411 414
           cdr["disposition"] = "failed";
412 415
           break;
413 416
 
417
+      case CallLeg::StatusChangeCause::InternalError:
418
+          cdr["disposition"] = "failed";
419
+          break;
420
+
414 421
     }
415 422
   }
416 423
 
... ...
@@ -455,8 +462,14 @@ void SyslogCDR::onStateChange(SBCCallLeg *call, const CallLeg::StatusChangeCause
455 462
         cdr["hangup_cause"] = "session timeout";
456 463
         break;
457 464
 
458
-      case CallLeg::StatusChangeCause::Unspecified:
459
-          cdr["hangup_cause"] = "other";
465
+      case CallLeg::StatusChangeCause::Other:
466
+        if (cause.param.desc) cdr["hangup_cause"] = cause.param.desc;
467
+        else cdr["hangup_cause"] = "other";
468
+        break;
469
+
470
+      case CallLeg::StatusChangeCause::InternalError:
471
+          cdr["hangup cause"] = "error";
472
+          cdr["hangup_initiator"] = "local";
460 473
           break;
461 474
     }
462 475