diff --git a/README.md b/README.md index ce7de4691..270eb9918 100644 --- a/README.md +++ b/README.md @@ -356,7 +356,8 @@ The options are described in more detail below. * -d, --delete-delay - Delete the call from memory after the specified delay from memory. + Delete the call from memory after the specified delay from memory. Can be set to zero for + immediate call deletion. * -r, --redis, -R, --redis-db, -b, --b2b-url @@ -865,6 +866,13 @@ of zero or more strings. The following flags are defined: result in an error reply (i.e. `"result": "error"`). The default is to reply with a warning only (i.e. `"result": "ok", "warning": ...`). +Other optional keys are: + +* `delete delay` + + Contains an integer and overrides the global command-line option `delete-delay`. Call/branch will be + deleted immediately if a zero is given. Value must be positive (in seconds) otherwise. + The reply message may contain additional keys with statistics about the deleted call. Those additional keys are the same as used in the `query` reply. diff --git a/daemon/call.c b/daemon/call.c index a708dc9d1..fe5879126 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -3495,7 +3495,7 @@ struct call_monologue *call_get_mono_dialogue(struct call *call, const str *from int call_delete_branch(struct callmaster *m, const str *callid, const str *branch, - const str *fromtag, const str *totag, bencode_item_t *output) + const str *fromtag, const str *totag, bencode_item_t *output, int delete_delay) { struct call *c; struct call_monologue *ml; @@ -3503,6 +3503,9 @@ int call_delete_branch(struct callmaster *m, const str *callid, const str *branc const str *match_tag; GSList *i; + if (delete_delay < 0) + delete_delay = m->conf.delete_delay; + c = call_get(callid, m); if (!c) { ilog(LOG_INFO, "Call-ID to delete not found"); @@ -3545,10 +3548,10 @@ int call_delete_branch(struct callmaster *m, const str *callid, const str *branc } */ - if (m->conf.delete_delay > 0) { + if (delete_delay > 0) { ilog(LOG_INFO, "Scheduling deletion of call branch '"STR_FORMAT"' in %d seconds", - STR_FMT(&ml->tag), m->conf.delete_delay); - ml->deleted = poller_now + m->conf.delete_delay; + STR_FMT(&ml->tag), delete_delay); + ml->deleted = poller_now + delete_delay; if (!c->ml_deleted || c->ml_deleted > ml->deleted) c->ml_deleted = ml->deleted; } @@ -3561,9 +3564,9 @@ int call_delete_branch(struct callmaster *m, const str *callid, const str *branc goto success_unlock; del_all: - if (m->conf.delete_delay > 0) { - ilog(LOG_INFO, "Scheduling deletion of entire call in %d seconds", m->conf.delete_delay); - c->deleted = poller_now + m->conf.delete_delay; + if (delete_delay > 0) { + ilog(LOG_INFO, "Scheduling deletion of entire call in %d seconds", delete_delay); + c->deleted = poller_now + delete_delay; rwlock_unlock_w(&c->master_lock); } else { diff --git a/daemon/call.h b/daemon/call.h index 51be41ef6..e6ea9df55 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -499,7 +499,7 @@ struct call_monologue *call_get_mono_dialogue(struct call *call, const str *from struct call *call_get(const str *callid, struct callmaster *m); int monologue_offer_answer(struct call_monologue *monologue, GQueue *streams, const struct sdp_ng_flags *flags); int call_delete_branch(struct callmaster *m, const str *callid, const str *branch, - const str *fromtag, const str *totag, bencode_item_t *output); + const str *fromtag, const str *totag, bencode_item_t *output, int delete_delay); void call_destroy(struct call *); enum call_stream_state call_stream_state_machine(struct packet_stream *); void call_media_unkernelize(struct call_media *media); diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index d6543b590..f1ba63ff8 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -369,7 +369,7 @@ str *call_delete_udp(char **out, struct callmaster *m) { str_init(&fromtag, out[RE_UDP_DQ_FROMTAG]); str_init(&totag, out[RE_UDP_DQ_TOTAG]); - if (call_delete_branch(m, &callid, &branch, &fromtag, &totag, NULL)) + if (call_delete_branch(m, &callid, &branch, &fromtag, &totag, NULL, -1)) return str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); return str_sprintf("%s 0\n", out[RE_UDP_COOKIE]); @@ -417,7 +417,7 @@ void call_delete_tcp(char **out, struct callmaster *m) { str callid; str_init(&callid, out[RE_TCP_D_CALLID]); - call_delete_branch(m, &callid, NULL, NULL, NULL, NULL); + call_delete_branch(m, &callid, NULL, NULL, NULL, NULL, -1); } static void call_status_iterator(struct call *c, struct control_stream *s) { @@ -748,7 +748,7 @@ const char *call_answer_ng(bencode_item_t *input, struct callmaster *m, bencode_ const char *call_delete_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output) { str fromtag, totag, viabranch, callid; bencode_item_t *flags, *it; - int fatal = 0; + int fatal = 0, delete_delay; if (!bencode_dictionary_get_str(input, "call-id", &callid)) return "No call-id in message"; @@ -764,8 +764,11 @@ const char *call_delete_ng(bencode_item_t *input, struct callmaster *m, bencode_ fatal = 1; } } + delete_delay = bencode_dictionary_get_integer(input, "delete-delay", -1); + if (delete_delay == -1) + delete_delay = bencode_dictionary_get_integer(input, "delete delay", -1); - if (call_delete_branch(m, &callid, &viabranch, &fromtag, &totag, output)) { + if (call_delete_branch(m, &callid, &viabranch, &fromtag, &totag, output, delete_delay)) { if (fatal) return "Call-ID not found or tags didn't match"; bencode_dictionary_add_string(output, "warning", "Call-ID not found or tags didn't match"); diff --git a/utils/ng-client b/utils/ng-client index 5d90fdb5d..b1aff63cd 100755 --- a/utils/ng-client +++ b/utils/ng-client @@ -41,13 +41,14 @@ GetOptions( 'strict-source' => \$options{'strict source'}, 'media-handover' => \$options{'media handover'}, 'TOS=i' => \$options{'TOS'}, + 'delete-delay=i' => \$options{'delete-delay'}, ) or die; my $cmd = shift(@ARGV) or die; my %packet = (command => $cmd); -for my $x (split(',', 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,TOS,DTLS,via-branch')) { +for my $x (split(',', 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,TOS,DTLS,via-branch,delete-delay')) { defined($options{$x}) and $packet{$x} = $options{$x}; } for my $x (split(',', 'trust address,symmetric,asymmetric,force,strict source,media handover,sip source address')) {