|
|
|
|
@ -746,6 +746,13 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu
|
|
|
|
|
call_ng_flags_list(out, input, "replace", call_ng_flags_replace, NULL);
|
|
|
|
|
call_ng_flags_list(out, input, "supports", call_ng_flags_supports, NULL);
|
|
|
|
|
|
|
|
|
|
bencode_dictionary_get_str(input, "call-id", &out->call_id);
|
|
|
|
|
bencode_dictionary_get_str(input, "from-tag", &out->from_tag);
|
|
|
|
|
bencode_dictionary_get_str(input, "to-tag", &out->to_tag);
|
|
|
|
|
bencode_dictionary_get_str(input, "via-branch", &out->via_branch);
|
|
|
|
|
bencode_dictionary_get_str(input, "label", &out->label);
|
|
|
|
|
bencode_dictionary_get_str(input, "address", &out->address);
|
|
|
|
|
|
|
|
|
|
diridx = 0;
|
|
|
|
|
if ((list = bencode_dictionary_get_expect(input, "direction", BENCODE_LIST))) {
|
|
|
|
|
for (it = list->child; it && diridx < 2; it = it->sibling)
|
|
|
|
|
@ -900,8 +907,7 @@ static const char *call_offer_answer_ng(bencode_item_t *input,
|
|
|
|
|
bencode_item_t *output, enum call_opmode opmode, const char* addr,
|
|
|
|
|
const endpoint_t *sin)
|
|
|
|
|
{
|
|
|
|
|
str sdp, fromtag, totag = STR_NULL, callid, viabranch;
|
|
|
|
|
str label = STR_NULL;
|
|
|
|
|
str sdp;
|
|
|
|
|
const char *errstr;
|
|
|
|
|
GQueue parsed = G_QUEUE_INIT;
|
|
|
|
|
GQueue streams = G_QUEUE_INIT;
|
|
|
|
|
@ -913,20 +919,18 @@ static const char *call_offer_answer_ng(bencode_item_t *input,
|
|
|
|
|
|
|
|
|
|
if (!bencode_dictionary_get_str(input, "sdp", &sdp))
|
|
|
|
|
return "No SDP body in message";
|
|
|
|
|
if (!bencode_dictionary_get_str(input, "call-id", &callid))
|
|
|
|
|
|
|
|
|
|
call_ng_process_flags(&flags, input, opmode);
|
|
|
|
|
|
|
|
|
|
if (!flags.call_id.s)
|
|
|
|
|
return "No call-id in message";
|
|
|
|
|
if (!bencode_dictionary_get_str(input, "from-tag", &fromtag))
|
|
|
|
|
if (!flags.from_tag.s)
|
|
|
|
|
return "No from-tag in message";
|
|
|
|
|
bencode_dictionary_get_str(input, "to-tag", &totag);
|
|
|
|
|
if (opmode == OP_ANSWER) {
|
|
|
|
|
if (!totag.s)
|
|
|
|
|
if (!flags.to_tag.s)
|
|
|
|
|
return "No to-tag in message";
|
|
|
|
|
str_swap(&totag, &fromtag);
|
|
|
|
|
str_swap(&flags.to_tag, &flags.from_tag);
|
|
|
|
|
}
|
|
|
|
|
bencode_dictionary_get_str(input, "via-branch", &viabranch);
|
|
|
|
|
bencode_dictionary_get_str(input, "label", &label);
|
|
|
|
|
|
|
|
|
|
call_ng_process_flags(&flags, input, opmode);
|
|
|
|
|
|
|
|
|
|
if (opmode == OP_OFFER) {
|
|
|
|
|
enum load_limit_reasons limit = call_offer_session_limit();
|
|
|
|
|
@ -955,7 +959,7 @@ static const char *call_offer_answer_ng(bencode_item_t *input,
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
/* OP_ANSWER; OP_OFFER && !IS_FOREIGN_CALL */
|
|
|
|
|
call = call_get(&callid);
|
|
|
|
|
call = call_get(&flags.call_id);
|
|
|
|
|
|
|
|
|
|
/* Failover scenario because of timeout on offer response: siprouter tries
|
|
|
|
|
* to establish session with another rtpengine2 even though rtpengine1
|
|
|
|
|
@ -969,12 +973,12 @@ static const char *call_offer_answer_ng(bencode_item_t *input,
|
|
|
|
|
rwlock_unlock_w(&call->master_lock);
|
|
|
|
|
call_destroy(call);
|
|
|
|
|
obj_put(call);
|
|
|
|
|
call = call_get_or_create(&callid, CT_OWN_CALL);
|
|
|
|
|
call = call_get_or_create(&flags.call_id, CT_OWN_CALL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* call == NULL, should create call */
|
|
|
|
|
call = call_get_or_create(&callid, CT_OWN_CALL);
|
|
|
|
|
call = call_get_or_create(&flags.call_id, CT_OWN_CALL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -993,7 +997,8 @@ static const char *call_offer_answer_ng(bencode_item_t *input,
|
|
|
|
|
* need to hold a ref until we're done sending the reply */
|
|
|
|
|
call_bencode_hold_ref(call, output);
|
|
|
|
|
|
|
|
|
|
monologue = call_get_mono_dialogue(call, &fromtag, &totag, viabranch.s ? &viabranch : NULL);
|
|
|
|
|
monologue = call_get_mono_dialogue(call, &flags.from_tag, &flags.to_tag,
|
|
|
|
|
flags.via_branch.s ? &flags.via_branch : NULL);
|
|
|
|
|
errstr = "Invalid dialogue association";
|
|
|
|
|
if (!monologue) {
|
|
|
|
|
rwlock_unlock_w(&call->master_lock);
|
|
|
|
|
@ -1006,8 +1011,6 @@ static const char *call_offer_answer_ng(bencode_item_t *input,
|
|
|
|
|
} else {
|
|
|
|
|
monologue->tagtype = TO_TAG;
|
|
|
|
|
}
|
|
|
|
|
if (label.s && !monologue->label.s)
|
|
|
|
|
call_str_cpy(call, &monologue->label, &label);
|
|
|
|
|
|
|
|
|
|
chopper = sdp_chopper_new(&sdp);
|
|
|
|
|
bencode_buffer_destroy_add(output->buffer, (free_func_t) sdp_chopper_destroy, chopper);
|
|
|
|
|
@ -1478,24 +1481,33 @@ const char *call_stop_recording_ng(bencode_item_t *input, bencode_item_t *output
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *media_block_match(struct call **call, struct call_monologue **monologue,
|
|
|
|
|
bencode_item_t *input)
|
|
|
|
|
struct sdp_ng_flags *flags, bencode_item_t *input)
|
|
|
|
|
{
|
|
|
|
|
str callid;
|
|
|
|
|
str s;
|
|
|
|
|
struct sdp_ng_flags flags_store;
|
|
|
|
|
|
|
|
|
|
if (!flags)
|
|
|
|
|
flags = &flags_store;
|
|
|
|
|
|
|
|
|
|
*call = NULL;
|
|
|
|
|
*monologue = NULL;
|
|
|
|
|
|
|
|
|
|
if (!bencode_dictionary_get_str(input, "call-id", &callid))
|
|
|
|
|
call_ng_process_flags(flags, input, OP_OTHER);
|
|
|
|
|
|
|
|
|
|
if (!flags->call_id.s)
|
|
|
|
|
return "No call-id in message";
|
|
|
|
|
*call = call_get_opmode(&callid, OP_OTHER);
|
|
|
|
|
*call = call_get_opmode(&flags->call_id, OP_OTHER);
|
|
|
|
|
if (!*call)
|
|
|
|
|
return "Unknown call-id";
|
|
|
|
|
|
|
|
|
|
// directional block?
|
|
|
|
|
if (bencode_dictionary_get_str(input, "address", &s)) {
|
|
|
|
|
// directional?
|
|
|
|
|
if (flags->label.s) {
|
|
|
|
|
*monologue = g_hash_table_lookup((*call)->labels, &flags->label);
|
|
|
|
|
if (!*monologue)
|
|
|
|
|
return "No monologue matching the given label";
|
|
|
|
|
}
|
|
|
|
|
else if (flags->address.s) {
|
|
|
|
|
sockaddr_t addr;
|
|
|
|
|
if (sockaddr_parse_any_str(&addr, &s))
|
|
|
|
|
if (sockaddr_parse_any_str(&addr, &flags->address))
|
|
|
|
|
return "Failed to parse network address";
|
|
|
|
|
// walk our structures to find a matching stream
|
|
|
|
|
for (GList *l = (*call)->monologues.head; l; l = l->next) {
|
|
|
|
|
@ -1516,8 +1528,8 @@ static const char *media_block_match(struct call **call, struct call_monologue *
|
|
|
|
|
found:
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
else if (bencode_dictionary_get_str(input, "from-tag", &s)) {
|
|
|
|
|
*monologue = call_get_mono_dialogue(*call, &s, NULL, NULL);
|
|
|
|
|
else if (flags->from_tag.s) {
|
|
|
|
|
*monologue = call_get_mono_dialogue(*call, &flags->from_tag, NULL, NULL);
|
|
|
|
|
if (!*monologue)
|
|
|
|
|
return "From-tag given, but no such tag exists";
|
|
|
|
|
}
|
|
|
|
|
@ -1530,14 +1542,12 @@ const char *call_start_forwarding_ng(bencode_item_t *input, bencode_item_t *outp
|
|
|
|
|
struct call *call;
|
|
|
|
|
struct call_monologue *monologue;
|
|
|
|
|
const char *errstr = NULL;
|
|
|
|
|
str metadata;
|
|
|
|
|
struct sdp_ng_flags flags;
|
|
|
|
|
|
|
|
|
|
errstr = media_block_match(&call, &monologue, input);
|
|
|
|
|
errstr = media_block_match(&call, &monologue, &flags, input);
|
|
|
|
|
if (errstr)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
bencode_dictionary_get_str(input, "metadata", &metadata);
|
|
|
|
|
|
|
|
|
|
if (monologue) {
|
|
|
|
|
ilog(LOG_INFO, "Start forwarding for single party (tag '" STR_FORMAT ")",
|
|
|
|
|
STR_FMT(&monologue->tag));
|
|
|
|
|
@ -1548,7 +1558,7 @@ const char *call_start_forwarding_ng(bencode_item_t *input, bencode_item_t *outp
|
|
|
|
|
call->rec_forwarding = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
recording_start(call, NULL, &metadata);
|
|
|
|
|
recording_start(call, NULL, &flags.metadata);
|
|
|
|
|
errstr = NULL;
|
|
|
|
|
out:
|
|
|
|
|
if (call) {
|
|
|
|
|
@ -1565,12 +1575,10 @@ const char *call_stop_forwarding_ng(bencode_item_t *input, bencode_item_t *outpu
|
|
|
|
|
const char *errstr = NULL;
|
|
|
|
|
struct sdp_ng_flags flags;
|
|
|
|
|
|
|
|
|
|
errstr = media_block_match(&call, &monologue, input);
|
|
|
|
|
errstr = media_block_match(&call, &monologue, &flags, input);
|
|
|
|
|
if (errstr)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
call_ng_process_flags(&flags, input, OP_OTHER);
|
|
|
|
|
|
|
|
|
|
if (monologue) {
|
|
|
|
|
ilog(LOG_INFO, "Stop forwarding for single party (tag '" STR_FORMAT ")",
|
|
|
|
|
STR_FMT(&monologue->tag));
|
|
|
|
|
@ -1603,8 +1611,9 @@ const char *call_block_dtmf_ng(bencode_item_t *input, bencode_item_t *output) {
|
|
|
|
|
struct call *call;
|
|
|
|
|
struct call_monologue *monologue;
|
|
|
|
|
const char *errstr = NULL;
|
|
|
|
|
struct sdp_ng_flags flags;
|
|
|
|
|
|
|
|
|
|
errstr = media_block_match(&call, &monologue, input);
|
|
|
|
|
errstr = media_block_match(&call, &monologue, &flags, input);
|
|
|
|
|
if (errstr)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
@ -1634,12 +1643,10 @@ const char *call_unblock_dtmf_ng(bencode_item_t *input, bencode_item_t *output)
|
|
|
|
|
const char *errstr = NULL;
|
|
|
|
|
struct sdp_ng_flags flags;
|
|
|
|
|
|
|
|
|
|
errstr = media_block_match(&call, &monologue, input);
|
|
|
|
|
errstr = media_block_match(&call, &monologue, &flags, input);
|
|
|
|
|
if (errstr)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
call_ng_process_flags(&flags, input, OP_OTHER);
|
|
|
|
|
|
|
|
|
|
if (monologue) {
|
|
|
|
|
ilog(LOG_INFO, "Unblocking directional DTMF (tag '" STR_FORMAT ")",
|
|
|
|
|
STR_FMT(&monologue->tag));
|
|
|
|
|
@ -1670,8 +1677,9 @@ const char *call_block_media_ng(bencode_item_t *input, bencode_item_t *output) {
|
|
|
|
|
struct call *call;
|
|
|
|
|
struct call_monologue *monologue;
|
|
|
|
|
const char *errstr = NULL;
|
|
|
|
|
struct sdp_ng_flags flags;
|
|
|
|
|
|
|
|
|
|
errstr = media_block_match(&call, &monologue, input);
|
|
|
|
|
errstr = media_block_match(&call, &monologue, &flags, input);
|
|
|
|
|
if (errstr)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
@ -1703,12 +1711,10 @@ const char *call_unblock_media_ng(bencode_item_t *input, bencode_item_t *output)
|
|
|
|
|
const char *errstr = NULL;
|
|
|
|
|
struct sdp_ng_flags flags;
|
|
|
|
|
|
|
|
|
|
errstr = media_block_match(&call, &monologue, input);
|
|
|
|
|
errstr = media_block_match(&call, &monologue, &flags, input);
|
|
|
|
|
if (errstr)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
call_ng_process_flags(&flags, input, OP_OTHER);
|
|
|
|
|
|
|
|
|
|
if (monologue) {
|
|
|
|
|
ilog(LOG_INFO, "Unblocking directional media (tag '" STR_FORMAT ")",
|
|
|
|
|
STR_FMT(&monologue->tag));
|
|
|
|
|
@ -1742,7 +1748,7 @@ out:
|
|
|
|
|
static const char *play_media_select_party(struct call **call, struct call_monologue **monologue,
|
|
|
|
|
bencode_item_t *input)
|
|
|
|
|
{
|
|
|
|
|
const char *err = media_block_match(call, monologue, input);
|
|
|
|
|
const char *err = media_block_match(call, monologue, NULL, input);
|
|
|
|
|
if (err)
|
|
|
|
|
return err;
|
|
|
|
|
if (!*monologue)
|
|
|
|
|
|