diff --git a/daemon/call.c b/daemon/call.c index 4e3581ff8..24d8a81bb 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1777,53 +1777,43 @@ str *call_lookup(char **out, struct callmaster *m) { return call_request_lookup(out, m, OP_ANSWER, "totag"); } -str *call_delete_udp(char **out, struct callmaster *m) { +static int call_delete_branch(struct callmaster *m, const str *callid, const str *branch, const str *fromtag, const str *totag) { struct call *c; - str *ret, callid, branch; struct callstream *cs; GList *l; - int i; + int ret, i; struct peer *p, *px; - DBG("got delete for callid '%s' and viabranch '%s'", - out[RE_UDP_DQ_CALLID], out[RE_UDP_DQ_VIABRANCH]); - - str_init(&callid, out[RE_UDP_DQ_CALLID]); - str_init(&branch, out[RE_UDP_DQ_VIABRANCH]); - rwlock_lock_r(&m->hashlock); - c = g_hash_table_lookup(m->callhash, &callid); + c = call_get(callid, NULL, m); if (!c) { - rwlock_unlock_r(&m->hashlock); - mylog(LOG_INFO, LOG_PREFIX_C "Call-ID to delete not found", STR_FMT(&callid)); + mylog(LOG_INFO, LOG_PREFIX_C "Call-ID to delete not found", STR_FMT(callid)); goto err; } - obj_hold(c); - mutex_lock(&c->lock); - rwlock_unlock_r(&m->hashlock); - log_info = &branch; - - if (out[RE_UDP_DQ_FROMTAG] && *out[RE_UDP_DQ_FROMTAG]) { - for (l = c->callstreams->head; l; l = l->next) { - cs = l->data; - mutex_lock(&cs->lock); + log_info = branch; - for (i = 0; i < 2; i++) { - p = &cs->peers[i]; - if (str_cmp(&p->tag, out[RE_UDP_DQ_FROMTAG])) - continue; - if (!out[RE_UDP_DQ_TOTAG] || !*out[RE_UDP_DQ_TOTAG]) - goto tag_match; + if (!fromtag || !fromtag->len) + goto no_tags; - px = &cs->peers[i ^ 1]; - if (str_cmp(&px->tag, out[RE_UDP_DQ_TOTAG])) - continue; + for (l = c->callstreams->head; l; l = l->next) { + cs = l->data; + mutex_lock(&cs->lock); + for (i = 0; i < 2; i++) { + p = &cs->peers[i]; + if (str_cmp_str(&p->tag, fromtag)) + continue; + if (!totag || !totag->len) goto tag_match; - } - mutex_unlock(&cs->lock); + px = &cs->peers[i ^ 1]; + if (str_cmp_str(&px->tag, totag)) + continue; + + goto tag_match; } + + mutex_unlock(&cs->lock); } mylog(LOG_INFO, LOG_PREFIX_C "Tags didn't match for delete message, ignoring", LOG_PARAMS_C(c)); @@ -1832,9 +1822,10 @@ str *call_delete_udp(char **out, struct callmaster *m) { tag_match: mutex_unlock(&cs->lock); - if (branch.s && branch.len) { - if (!g_hash_table_remove(c->branches, &branch)) { - mylog(LOG_INFO, LOG_PREFIX_CI "Branch to delete doesn't exist", STR_FMT(&c->callid), STR_FMT(&branch)); +no_tags: + if (branch && branch->len) { + if (!g_hash_table_remove(c->branches, branch)) { + mylog(LOG_INFO, LOG_PREFIX_CI "Branch to delete doesn't exist", STR_FMT(&c->callid), STR_FMT(branch)); goto err; } @@ -1853,13 +1844,13 @@ tag_match: success_unlock: mutex_unlock(&c->lock); success: - ret = str_sprintf("%s 0\n", out[RE_UDP_COOKIE]); + ret = 0; goto out; err: if (c) mutex_unlock(&c->lock); - ret = str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); + ret = -1; goto out; out: @@ -1869,6 +1860,23 @@ out: return ret; } +str *call_delete_udp(char **out, struct callmaster *m) { + str callid, branch, fromtag, totag; + + DBG("got delete for callid '%s' and viabranch '%s'", + out[RE_UDP_DQ_CALLID], out[RE_UDP_DQ_VIABRANCH]); + + str_init(&callid, out[RE_UDP_DQ_CALLID]); + str_init(&branch, out[RE_UDP_DQ_VIABRANCH]); + 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)) + return str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); + + return str_sprintf("%s 0\n", out[RE_UDP_COOKIE]); +} + str *call_query_udp(char **out, struct callmaster *m) { struct call *c; str *ret, callid; @@ -1947,22 +1955,10 @@ out: } void call_delete(char **out, struct callmaster *m) { - struct call *c; str callid; str_init(&callid, out[RE_TCP_D_CALLID]); - rwlock_lock_r(&m->hashlock); - c = g_hash_table_lookup(m->callhash, &callid); - if (!c) { - rwlock_unlock_r(&m->hashlock); - return; - } - obj_hold(c); - rwlock_unlock_r(&m->hashlock); - - /* delete whole list, as we don't have branches in tcp controller */ - call_destroy(c); - obj_put(c); + call_delete_branch(m, &callid, NULL, NULL, NULL); } @@ -2196,3 +2192,20 @@ const char *call_offer(bencode_item_t *input, struct callmaster *m, bencode_item const char *call_answer(bencode_item_t *input, struct callmaster *m, bencode_item_t *output) { return call_offer_answer(input, m, output, OP_ANSWER, "to-tag"); } + +const char *call_delete_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output) { + str fromtag, totag, viabranch, callid; + + if (!bencode_dictionary_get_str(input, "call-id", &callid)) + return "No call-id in message"; + if (!bencode_dictionary_get_str(input, "from-tag", &fromtag)) + return "No from-tag in message"; + bencode_dictionary_get_str(input, "to-tag", &totag); + bencode_dictionary_get_str(input, "via-branch", &viabranch); + + if (call_delete_branch(m, &callid, &viabranch, &fromtag, &totag)) + return "Call-ID not found or tags didn't match"; + + bencode_dictionary_add_string(output, "result", "ok"); + return NULL; +} diff --git a/daemon/call.h b/daemon/call.h index c881b2eda..adc48a613 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -188,6 +188,7 @@ static inline str *call_str_init_dup(struct call *c, char *s) { const char *call_offer(bencode_item_t *, struct callmaster *, bencode_item_t *); const char *call_answer(bencode_item_t *, struct callmaster *, bencode_item_t *); +const char *call_delete_ng(bencode_item_t *, struct callmaster *, bencode_item_t *); diff --git a/daemon/control_ng.c b/daemon/control_ng.c index 803f3ee12..74f53092c 100644 --- a/daemon/control_ng.c +++ b/daemon/control_ng.c @@ -56,12 +56,12 @@ static void control_ng_incoming(struct obj *obj, str *buf, struct sockaddr_in6 * errstr = NULL; if (!str_cmp(&cmd, "ping")) bencode_dictionary_add_string(resp, "result", "pong"); - else if (!str_cmp(&cmd, "offer")) { + else if (!str_cmp(&cmd, "offer")) errstr = call_offer(dict, c->callmaster, resp); - } - else if (!str_cmp(&cmd, "answer")) { + else if (!str_cmp(&cmd, "answer")) errstr = call_answer(dict, c->callmaster, resp); - } + else if (!str_cmp(&cmd, "delete")) + errstr = call_delete_ng(dict, c->callmaster, resp); else errstr = "Unrecognized command";