diff --git a/README.md b/README.md index da4ab0f41..4d8567821 100644 --- a/README.md +++ b/README.md @@ -499,7 +499,8 @@ The options are described in more detail below. Enables and sets the URI for an XMLRPC callback to be made when a call is torn down due to packet timeout. The special code `%%` can be used in place of an IP address, in which case the source address - of the originating request will be used. + of the originating request (or alternatively the address specified using the + `xmlrpc-callback` *ng* protocol option) will be used. * -x, --xmlrpc-format @@ -1443,6 +1444,11 @@ Optionally included keys are: dictionary. The response dictionary may also contain the optional key `message` with an explanatory string. No other key is required in the response dictionary. +* `xmlrpc-callback` + + Contains a string that encodes an IP address (either IPv4 or IPv6) in printable format. + If specified, then this address will be used as destination address for the XMLRPC timeout + callback (see `b2b-url` option). An example of a complete `offer` request dictionary could be (SDP body abbreviated): diff --git a/daemon/call.c b/daemon/call.c index 9e0b61e41..a7db02ab9 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -423,9 +423,15 @@ void kill_calls_timer(GSList *list, const char *url) { rwlock_lock_r(&ca->master_lock); + const sockaddr_t *cb_addr; + if (ca->xmlrpc_callback.family) + cb_addr = &ca->xmlrpc_callback; + else + cb_addr = &ca->created_from_addr; + if (url_prefix) { snprintf(url_buf, sizeof(url_buf), "%s%s%s", - url_prefix, sockaddr_print_buf(&ca->created_from_addr), + url_prefix, sockaddr_print_buf(cb_addr), url_suffix); } else diff --git a/daemon/call.h b/daemon/call.h index 4623f6cd4..dc372b2b5 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -398,6 +398,7 @@ struct call { unsigned char tos; char *created_from; sockaddr_t created_from_addr; + sockaddr_t xmlrpc_callback; unsigned int redis_hosted_db; unsigned int foreign_call; // created_via_redis_notify call diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 14a158a6c..592cbeca0 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -705,6 +705,12 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu bencode_dictionary_get_str(input, "metadata", &out->metadata); out->ptime = bencode_dictionary_get_int_str(input, "ptime", 0); + if (bencode_dictionary_get_str(input, "xmlrpc-callback", &s)) { + if (sockaddr_parse_any_str(&out->xmlrpc_callback, &s)) + ilog(LOG_WARN, "Failed to parse 'xmlrpc-callback' address '" STR_FORMAT "'", + STR_FMT(&s)); + } + if ((dict = bencode_dictionary_get_expect(input, "codec", BENCODE_DICTIONARY))) { call_ng_flags_list(out, dict, "strip", call_ng_flags_codec_ht, out->codec_strip); call_ng_flags_list(out, dict, "offer", call_ng_flags_codec_list, &out->codec_offer); @@ -854,6 +860,9 @@ static const char *call_offer_answer_ng(bencode_item_t *input, call->created_from = call_strdup(call, addr); call->created_from_addr = sin->address; } + if (flags.xmlrpc_callback.family) + call->xmlrpc_callback = flags.xmlrpc_callback; + /* At least the random ICE strings are contained within the call struct, so we * need to hold a ref until we're done sending the reply */ call_bencode_hold_ref(call, output); diff --git a/daemon/call_interfaces.h b/daemon/call_interfaces.h index 7e60a7837..b91ed6230 100644 --- a/daemon/call_interfaces.h +++ b/daemon/call_interfaces.h @@ -31,6 +31,7 @@ struct sdp_ng_flags { int tos; str record_call_str; str metadata; + sockaddr_t xmlrpc_callback; GHashTable *codec_strip; GQueue codec_offer; GQueue codec_transcode; diff --git a/utils/rtpengine-ng-client b/utils/rtpengine-ng-client index 35785aeff..bf798d8f5 100755 --- a/utils/rtpengine-ng-client +++ b/utils/rtpengine-ng-client @@ -55,13 +55,14 @@ GetOptions( 'codec-options-flat' => \$options{'codec options flag'}, 'flags=s@' => \$options{'flags'}, 'supports=s@' => \$options{'supports'}, + 'xmlrpc-callback=s' => \$options{'xmlrpc-callback'}, ) 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,DTLS,via-branch,media address,ptime')) { +for my $x (split(/,/, 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,DTLS,via-branch,media address,ptime,xmlrpc-callback')) { defined($options{$x}) and $packet{$x} = \$options{$x}; } for my $x (split(/,/, 'TOS,delete-delay')) {