diff --git a/daemon/call.c b/daemon/call.c index 54b53f235..f5a4afa88 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -4581,10 +4581,11 @@ static void monologue_stop(struct call_monologue *ml) { } -int call_delete_branch(const str *callid, const str *branch, +// call must be locked in W. +// unlocks the call and releases the reference prior to returning, even on error. +int call_delete_branch(struct call *c, const str *branch, const str *fromtag, const str *totag, bencode_item_t *output, int delete_delay) { - struct call *c; struct call_monologue *ml; int ret; const str *match_tag; @@ -4594,12 +4595,6 @@ int call_delete_branch(const str *callid, const str *branch, if (delete_delay < 0) delete_delay = rtpe_config.delete_delay; - c = call_get(callid); - if (!c) { - ilog(LOG_INFO, "Call-ID to delete not found"); - goto err; - } - for (i = c->monologues.head; i; i = i->next) { ml = i->data; gettimeofday(&(ml->terminated), NULL); @@ -4689,16 +4684,26 @@ success: goto out; err: - if (c) - rwlock_unlock_w(&c->master_lock); + rwlock_unlock_w(&c->master_lock); ret = -1; goto out; out: - if (c) { - if (update) - redis_update_onekey(c, rtpe_redis_write); - obj_put(c); - } + if (update) + redis_update_onekey(c, rtpe_redis_write); + obj_put(c); + return ret; } + + +int call_delete_branch_by_id(const str *callid, const str *branch, + const str *fromtag, const str *totag, bencode_item_t *output, int delete_delay) +{ + struct call *c = call_get(callid); + if (!c) { + ilog(LOG_INFO, "Call-ID to delete not found"); + return -1; + } + return call_delete_branch(c, branch, fromtag, totag, output, delete_delay); +} diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 36c736d48..aa02b4a76 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -373,7 +373,7 @@ str *call_delete_udp(char **out) { str_init(&fromtag, out[RE_UDP_DQ_FROMTAG]); str_init(&totag, out[RE_UDP_DQ_TOTAG]); - if (call_delete_branch(&callid, &branch, &fromtag, &totag, NULL, -1)) + if (call_delete_branch_by_id(&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) { str callid; str_init(&callid, out[RE_TCP_D_CALLID]); - call_delete_branch(&callid, NULL, NULL, NULL, NULL, -1); + call_delete_branch_by_id(&callid, NULL, NULL, NULL, NULL, -1); } static void call_status_iterator(struct call *c, struct streambuf_stream *s) { @@ -2146,7 +2146,7 @@ const char *call_delete_ng(bencode_item_t *input, bencode_item_t *output) { } } - if (call_delete_branch(&callid, &viabranch, &fromtag, &totag, output, delete_delay)) { + if (call_delete_branch_by_id(&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/include/call.h b/include/call.h index 7dc5c16bc..343d1a80e 100644 --- a/include/call.h +++ b/include/call.h @@ -734,7 +734,9 @@ int monologue_subscribe_answer(struct call_monologue *dst, struct sdp_ng_flags * GQueue *); int monologue_unsubscribe(struct call_monologue *dst, struct sdp_ng_flags *); void monologue_destroy(struct call_monologue *ml); -int call_delete_branch(const str *callid, const str *branch, +int call_delete_branch_by_id(const str *callid, const str *branch, + const str *fromtag, const str *totag, bencode_item_t *output, int delete_delay); +int call_delete_branch(struct call *, const str *branch, const str *fromtag, const str *totag, bencode_item_t *output, int delete_delay); void call_destroy(struct call *); struct call_media *call_media_new(struct call *call);