diff --git a/daemon/call.c b/daemon/call.c index e44e83d7e..77deea2d3 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -122,7 +122,15 @@ const struct transport_protocol transport_protocols[] = { }; const int num_transport_protocols = G_N_ELEMENTS(transport_protocols); +const char * get_term_reason_text(char *buf, enum termination_reason t) { + if (t==TIMEOUT) { buf = "TIMEOUT"; return buf; } + if (t==REGULAR) { buf = "REGULAR"; return buf; } + if (t==FORCED) { buf = "FORCED"; return buf; } + if (t==SILENT_TIMEOUT) { buf = "SILENT_TIMEOUT"; return buf; } + buf = "UNKNOWN"; + return buf; +} static void determine_handler(struct packet_stream *in, const struct packet_stream *out); @@ -981,6 +989,7 @@ static int call_timer_delete_monologues(struct call *c) { } __monologue_destroy(ml); + ml->deleted = 0; if (!g_hash_table_size(c->tags)) { @@ -1015,6 +1024,9 @@ static void call_timer_iterator(void *key, void *val, void *ptr) { int good = 0; struct packet_stream *ps; struct stream_fd *sfd; + int tmp_t_reason=0; + struct call_monologue *ml; + GSList *i; rwlock_lock_r(&c->master_lock); log_info_call(c); @@ -1056,8 +1068,11 @@ no_sfd: goto next; check = cm->conf.timeout; - if (!MEDIA_ISSET(ps->media, RECV) || !sfd) + tmp_t_reason = 1; + if (!MEDIA_ISSET(ps->media, RECV) || !sfd) { check = cm->conf.silent_timeout; + tmp_t_reason = 2; + } if (poller_now - ps->last_packet < check) good = 1; @@ -1069,6 +1084,18 @@ next: if (good) goto out; + for (i = c->monologues; i; i = i->next) { + ml = i->data; + ml->terminated = time(NULL); + if (tmp_t_reason==1) { + ml->term_reason = TIMEOUT; + } else if (tmp_t_reason==2) { + ml->term_reason = SILENT_TIMEOUT; + } else { + ml->term_reason = UNKNOWN; + } + } + ilog(LOG_INFO, "Closing call due to timeout"); drop: @@ -2313,6 +2340,7 @@ void call_destroy(struct call *c) { GList *k, *o; char buf[64]; static const int CDRBUFLENGTH = 4096*2; + char reasonbuf[16]; memset(&reasonbuf,0,16); char cdrbuffer[CDRBUFLENGTH]; memset(&cdrbuffer,0,CDRBUFLENGTH); char* cdrbufcur = cdrbuffer; int cdrlinecnt = 0; @@ -2344,11 +2372,10 @@ void call_destroy(struct call *c) { "ml%i_termination=%s, " "ml%i_local_tag=%s, " "ml%i_remote_tag=%s, ", - cdrlinecnt, (unsigned int)ml->created, - cdrlinecnt, (unsigned int)poller_now, - cdrlinecnt, (unsigned int)poller_now-(unsigned int)ml->created, - cdrlinecnt, "TOBEDONE", + cdrlinecnt, (unsigned int)ml->terminated, + cdrlinecnt, (unsigned int)ml->terminated-(unsigned int)ml->created, + cdrlinecnt, get_term_reason_text(reasonbuf,ml->term_reason), cdrlinecnt, ml->tag.s, cdrlinecnt, ml->active_dialogue ? ml->active_dialogue->tag.s : "(none)"); } @@ -2804,6 +2831,7 @@ int call_delete_branch(struct callmaster *m, const str *callid, const str *branc struct call_monologue *ml; int ret; const str *match_tag; + GSList *i; c = call_get(callid, m); if (!c) { @@ -2811,6 +2839,12 @@ int call_delete_branch(struct callmaster *m, const str *callid, const str *branc goto err; } + for (i = c->monologues; i; i = i->next) { + ml = i->data; + ml->terminated = time(NULL); + ml->term_reason = REGULAR; + } + if (!fromtag || !fromtag->s || !fromtag->len) goto del_all; @@ -2843,7 +2877,7 @@ int call_delete_branch(struct callmaster *m, const str *callid, const str *branc ilog(LOG_INFO, "Scheduling deletion of call branch '"STR_FORMAT"' in %d seconds", STR_FMT(&ml->tag), DELETE_DELAY); - ml->deleted = poller_now + 30; + ml->deleted = poller_now + DELETE_DELAY; if (!c->ml_deleted || c->ml_deleted > ml->deleted) c->ml_deleted = ml->deleted; goto success_unlock; diff --git a/daemon/call.h b/daemon/call.h index 2a37b8331..f0b8ea5af 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -12,7 +12,13 @@ #include "compat.h" - +enum termination_reason { + UNKNOWN=0, + REGULAR=1, + FORCED=2, + TIMEOUT=3, + SILENT_TIMEOUT=4 +}; enum stream_address_format { SAF_TCP, @@ -299,6 +305,8 @@ struct call_monologue { str tag; time_t created; /* RO */ time_t deleted; + time_t terminated; + enum termination_reason term_reason; GHashTable *other_tags; struct call_monologue *active_dialogue;