From 1e66618bede422537cc6a55366c284b55c2afa83 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Thu, 12 Jan 2017 12:44:59 +0100 Subject: [PATCH] TT#8901 support soundsets * add invite_allowip_soundset as example Change-Id: I08d3918b91ea4baa64f7bddfffee18b2374647a3 --- bin/check.sh | 11 ++ bin/create_soundsets.pl | 140 ++++++++++++++++++ bin/set_preferences.pl | 27 +++- debian/control | 1 + lib/Sipwise/API.pm | 54 +++++++ .../invite_allowip_soundset/0001_test.yml.tt2 | 30 ++++ .../invite_allowip_soundset/0003_test.yml.tt2 | 98 ++++++++++++ .../invite_allowip_soundset/0004_test.yml.tt2 | 19 +++ .../invite_allowip_soundset/0005_test.yml.tt2 | 33 +++++ .../invite_allowip_soundset/0006_test.yml.tt2 | 23 +++ scenarios/invite_allowip_soundset/prefs.json | 11 ++ .../invite_allowip_soundset/scenario.yml | 38 +++++ .../sipp_scenario00.xml | 110 ++++++++++++++ .../invite_allowip_soundset/soundsets.yml | 7 + sounds/no_sh.wav | Bin 0 -> 13016 bytes 15 files changed, 596 insertions(+), 6 deletions(-) create mode 100755 bin/create_soundsets.pl create mode 100644 scenarios/invite_allowip_soundset/0001_test.yml.tt2 create mode 100644 scenarios/invite_allowip_soundset/0003_test.yml.tt2 create mode 100644 scenarios/invite_allowip_soundset/0004_test.yml.tt2 create mode 100644 scenarios/invite_allowip_soundset/0005_test.yml.tt2 create mode 100644 scenarios/invite_allowip_soundset/0006_test.yml.tt2 create mode 100644 scenarios/invite_allowip_soundset/prefs.json create mode 100644 scenarios/invite_allowip_soundset/scenario.yml create mode 100644 scenarios/invite_allowip_soundset/sipp_scenario00.xml create mode 100644 scenarios/invite_allowip_soundset/soundsets.yml create mode 100644 sounds/no_sh.wav diff --git a/bin/check.sh b/bin/check.sh index ff6ce1be..01917028 100755 --- a/bin/check.sh +++ b/bin/check.sh @@ -125,6 +125,12 @@ function create_voip_prefs "${BIN_DIR}/create_ncos.pl" "${SCEN_CHECK_DIR}/ncos.yml" fi + if [ -f "${SCEN_CHECK_DIR}/soundsets.yml" ]; then + echo "$(date) - Creating soundsets" + "${BIN_DIR}/create_soundsets.pl" \ + "${SCEN_CHECK_DIR}/soundsets.yml" "${SCEN_CHECK_DIR}/scenario_ids.yml" + fi + if [ -f "${SCEN_CHECK_DIR}/peer.yml" ]; then echo "$(date) - Creating peers" "${BIN_DIR}/create_peers.pl" \ @@ -176,6 +182,11 @@ function delete_voip sed -e "s:$(cat "${SCEN_CHECK_DIR}/hosts")::" -i /etc/hosts rm "${SCEN_CHECK_DIR}/hosts" fi + + if [ -f "${SCEN_CHECK_DIR}/soundsets.yml" ]; then + echo "$(date) - Deleting soundsets" + "${BIN_DIR}/create_soundsets.pl" -delete "${SCEN_CHECK_DIR}/soundsets.yml" + fi } function delete_locations diff --git a/bin/create_soundsets.pl b/bin/create_soundsets.pl new file mode 100755 index 00000000..04e44ca3 --- /dev/null +++ b/bin/create_soundsets.pl @@ -0,0 +1,140 @@ +#!/usr/bin/perl +# +# Copyright: 2013-2016 Sipwise Development Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# On Debian systems, the complete text of the GNU General +# Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". +# +use strict; +use warnings; + +use English; +use Getopt::Long; +use Cwd 'abs_path'; +use Config::Tiny; +use Sipwise::API qw(all); +use YAML qw{ DumpFile LoadFile }; +use File::Basename qw{ basename }; + +my $config = Config::Tiny->read('/etc/default/ngcp-api'); +my $opts; +if ($config) { + $opts = {}; + $opts->{host} = $config->{_}->{NGCP_API_IP}; + $opts->{port} = $config->{_}->{NGCP_API_PORT}; + $opts->{sslverify} = $config->{_}->{NGCP_API_SSLVERIFY}; +} +my $api = Sipwise::API->new($opts); +$opts = $api->opts; +my $del = 0; +my $ids; +my $ids_path; + +sub usage { + return "Usage:\n$PROGRAM_NAME scenario.yml scenarios_ids.yml\n". + "Options:\n". + " -delete\n". + " -d debug\n". + " -h this help\n"; +} +my $help = 0; +GetOptions ("h|help" => \$help, + "d|debug" => \$opts->{verbose}, + "delete" => \$del) + or die("Error in command line arguments\n".usage()); + +die(usage()) unless (!$help); +if(!$del) { + die("Error: wrong number of arguments\n".usage()) unless ($#ARGV == 1); +} else { + die("Error: wrong number of arguments\n".usage()) unless ($#ARGV == 0); +} + +sub manage_soundfiles +{ + my ($data, $id) = @_; + + foreach my $sf (sort keys %{$data->{sounds}}) + { + my $sf_data = $data->{sounds}->{$sf}; + my $filename = $sf_data->{filename}; + $sf_data->{set_id} = $data->{id}; + $sf_data->{handle} = $sf; + $sf_data->{filename} = basename($filename, '.wav'); + $api->upload_soundfile($sf_data, abs_path($filename)); + print "[$filename] uploaded\n"; + } + return; +} + +sub do_create +{ + my $data = shift; + foreach my $st (sort keys %{$data->{soundsets}}) + { + my $st_data = { + name => $st, + reseller_id => $data->{soundsets}->{$st}->{reseller_id} + }; + $data->{soundsets}->{$st}->{id} = $api->check_soundset_exists($st_data); + if(defined $data->{soundsets}->{$st}->{id}) { + print "soundset[$st] already there [$data->{soundsets}->{$st}->{id}]\n"; + } else { + $data->{soundsets}->{$st}->{id} = $api->create_soundset($st_data); + print "soundset [$st]: created [$data->{soundsets}->{$st}->{id}]\n"; + manage_soundfiles($data->{soundsets}->{$st}); + } + $ids->{soundsets}->{$st}->{id} = $data->{soundsets}->{$st}->{id}; + } + return; +} + +sub do_delete +{ + my $data = shift; + foreach my $st (sort keys %{$data->{soundsets}}) + { + my $st_data = { + name => $st, + reseller_id => $data->{soundsets}->{$st}->{reseller_id} + }; + $data->{soundsets}->{$st}->{id} = $api->check_soundset_exists($st_data); + if(defined $data->{soundsets}->{$st}->{id}) { + $api->delete_soundset($data->{soundsets}->{$st}->{id}); + print "delete soundset[$st] -> [$data->{soundsets}->{$st}->{id}]\n"; + } + } + return; +} + +sub main { + my $r = shift; + + if ($del) { + return do_delete($r); + } else { + return do_create($r); + } +} + +if(! $del) { + $ids_path = abs_path($ARGV[1]); + $ids = LoadFile($ids_path); +} +main(LoadFile(abs_path($ARGV[0])), $ids); +if(! $del) { + DumpFile($ids_path, $ids); +} diff --git a/bin/set_preferences.pl b/bin/set_preferences.pl index 8418c472..97fba9b1 100755 --- a/bin/set_preferences.pl +++ b/bin/set_preferences.pl @@ -54,6 +54,23 @@ GetOptions ("h|help" => \$help, "d|debug" => \$opts->{verbose}) die(usage()) unless (!$help); die("Error: wrong number of arguments\n".usage()) unless ($#ARGV == 0); +sub resolve_ids { + my $prefs = shift; + return $prefs; + my $key; + if(defined $prefs->{sound_set}) { + $key = $prefs->{sound_set}; + my $id = $api->check_soundset_exists({name => $key}); + if($id) { + $prefs->{sound_set} = $id; + print "soundset[$key] => $prefs->{sound_set}\n"; + } else { + die("soundset[$key] not found\n"); + } + } + return $prefs; +} + sub merge { my $a = shift; @@ -163,21 +180,20 @@ sub set_peer_preferences sub main { my $prefs = shift; - my $peers; - my $rule_set; for my $key (keys %{$prefs}) { + my $prefs_id = resolve_ids($prefs->{$key}); print "processing $key\n"; if ( $key =~ /@/ ) { my @fields = split /@/, $key; if (!$fields[0]) { - set_domain_preferences($fields[1], $prefs->{$key}); + set_domain_preferences($fields[1], $prefs_id); } else { - set_subscriber_preferences($fields[0], $fields[1], $prefs->{$key}); + set_subscriber_preferences($fields[0], $fields[1], $prefs_id); } } else { - set_peer_preferences($key, $prefs->{$key}); + set_peer_preferences($key, $prefs_id); } } exit; @@ -197,5 +213,4 @@ sub get_json { } my $cf = get_json($ARGV[0]); - main($cf); diff --git a/debian/control b/debian/control index c286432c..3397ce91 100644 --- a/debian/control +++ b/debian/control @@ -11,6 +11,7 @@ Package: kamailio-config-tests Architecture: all Depends: curl, + libfile-slurp-perl, libgraphviz-perl, libjson-perl, libtemplate-perl, diff --git a/lib/Sipwise/API.pm b/lib/Sipwise/API.pm index 502be4e0..65901835 100644 --- a/lib/Sipwise/API.pm +++ b/lib/Sipwise/API.pm @@ -29,6 +29,7 @@ use LWP::UserAgent; use IO::Socket::SSL; use URI; use Data::Dumper; +use File::Slurp; my $opts_default = { host => '127.0.0.1', @@ -90,6 +91,21 @@ sub do_request { return $res; } +sub _do_binary_request { + my ($self, $ua, $url, $filename, $ct) = @_; + my $content; + + my $req = HTTP::Request->new('POST', $url); + $req->header('Content-Type' => $ct); + $req->header('Prefer' => 'return=representation'); + $req->content(read_file($filename)); + my $res = $ua->request($req); + if(!$res->is_success) { + print "$url\n"; + } + return $res; +} + sub do_query { my $self = shift; my $ua = shift; @@ -645,4 +661,42 @@ sub delete_ncoslnpcarrier { return $self->_delete($urldata); } +sub check_soundset_exists { + my ($self, $data) = @_; + my $urldata = "/api/soundsets/"; + my $collection_id = 'ngcp:soundsets'; + + return $self->_exists($data, $urldata, $collection_id); +} + +sub create_soundset { + my ($self, $data) = @_; + my $urldata = '/api/soundsets/'; + + return $self->_create($data, $urldata); +} + +sub delete_soundset { + my ($self, $id) = @_; + my $urldata = "/api/soundsets/${id}"; + + return $self->_delete($urldata); +} + +sub upload_soundfile { + my ($self, $data, $filepath) = @_; + my $urldata = "/api/soundfiles/?". + "filename=$data->{filename}&handle=$data->{handle}". + "&set_id=$data->{set_id}&loopplay=$data->{loopplay}"; + my $urlbase = 'https://'.$self->{opts}->{host}.':'.$self->{opts}->{port}; + + my $ua = $self->create_ua(); + my $res = $self->_do_binary_request($ua, $urlbase.$urldata, + $filepath, 'audio/x-wav'); + if(! $res->is_success) { + die $res->as_string; + } + return; +} + 1; diff --git a/scenarios/invite_allowip_soundset/0001_test.yml.tt2 b/scenarios/invite_allowip_soundset/0001_test.yml.tt2 new file mode 100644 index 00000000..bc4420e6 --- /dev/null +++ b/scenarios/invite_allowip_soundset/0001_test.yml.tt2 @@ -0,0 +1,30 @@ +flow: + - start|DEFAULT_ROUTE: + - start|ROUTE_NET_INFO: + - return|ROUTE_NET_INFO: + - start|ROUTE_PRX_REQUEST: + - start|ROUTE_INITVARS: + - return|ROUTE_INITVARS: + - start|ROUTE_INVITE: + - start|ROUTE_LOAD_CALLEE_DOMAIN_PREF: + - start|ROUTE_CLEAR_CALLEE_DOMAIN_PREF: + - return|ROUTE_CLEAR_CALLEE_DOMAIN_PREF: + - return|ROUTE_LOAD_CALLEE_DOMAIN_PREF: + - start|ROUTE_FIND_CALLER: + - start|ROUTE_AUTH: + - exit|ROUTE_AUTH: +sip_in: + - '^INVITE' + - 'Contact: sip:testuser1002@' + - 'CSeq: 1 INVITE' + - 'Max-Forwards: 69' + - 'Content-Type: application/sdp' +sip_out: + - [ + '^SIP/2.0 100 Trying', + 'CSeq: 1 INVITE' + ] + - [ + '^SIP/2.0 407 Proxy Authentication Required', + 'CSeq: 1 INVITE' + ] diff --git a/scenarios/invite_allowip_soundset/0003_test.yml.tt2 b/scenarios/invite_allowip_soundset/0003_test.yml.tt2 new file mode 100644 index 00000000..de323c2f --- /dev/null +++ b/scenarios/invite_allowip_soundset/0003_test.yml.tt2 @@ -0,0 +1,98 @@ +flow: + - start|DEFAULT_ROUTE: + - start|ROUTE_NET_INFO: + - return|ROUTE_NET_INFO: + - start|ROUTE_PRX_REQUEST: + - start|ROUTE_INITVARS: + - return|ROUTE_INITVARS: + - start|ROUTE_INVITE: + - start|ROUTE_LOAD_CALLEE_DOMAIN_PREF: + - start|ROUTE_CLEAR_CALLEE_DOMAIN_PREF: + - return|ROUTE_CLEAR_CALLEE_DOMAIN_PREF: + - return|ROUTE_LOAD_CALLEE_DOMAIN_PREF: + - start|ROUTE_FIND_CALLER: + - start|ROUTE_AUTH: + - start|ROUTE_AUTH_HELPER: + $fd: spce.test + $var(realm_user): testuser1002 + $var(realm_domain): spce.test + - return|ROUTE_AUTH_HELPER: + $avp(orig_acc_caller_user): ['testuser1002'] + $avp(orig_acc_caller_domain): ['spce.test'] + - start|ROUTE_ADD_CALLINFO_REPLY: + - start|ROUTE_ADD_CALLINFO_CALLER_PRIMARY: + - return|ROUTE_ADD_CALLINFO_CALLER_PRIMARY: + - return|ROUTE_ADD_CALLINFO_REPLY: + - return|ROUTE_AUTH: + - return|ROUTE_FIND_CALLER: + - start|ROUTE_LOAD_CALLER_PREF: + - start|ROUTE_CLEAR_CALLER_PREF: + - return|ROUTE_CLEAR_CALLER_PREF: + - start|ROUTE_LOAD_CALLER_CONTRACT_PREF: + - return|ROUTE_LOAD_CALLER_CONTRACT_PREF: + - return|ROUTE_LOAD_CALLER_PREF: + $xavp(caller_usr_prefs[0]=>allowed_ips_grp[*]): '\d+' + $xavp(caller_real_prefs[0]=>allowed_ips_grp[*]): '\d+' + - start|ROUTE_DLG_MANAGE: + - return|ROUTE_DLG_MANAGE: + - start|ROUTE_ACC_FAILURE: + - start|ROUTE_ACC_CALLER: + - return|ROUTE_ACC_CALLER: + - start|ROUTE_ACC_CALLEE: + - return|ROUTE_ACC_CALLEE: + - return|ROUTE_ACC_FAILURE: + - start|ROUTE_EARLY_REJECT: + - start|ROUTE_TO_APPSRV: + - start|ROUTE_LOAD_APPSRV: + - start|ROUTE_CNT_DLG_CHECK: + - return|ROUTE_CNT_DLG_CHECK: + - return|ROUTE_LOAD_APPSRV: + - start|ROUTE_OUTBOUND: + - start|BRANCH_ROUTE_NO_SBC: + - start|ROUTE_BRANCH_ACC_RTP: + - return|ROUTE_BRANCH_ACC_RTP: + - start|ROUTE_FILTER_PRACK: + - return|ROUTE_FILTER_PRACK: + - start|ROUTE_ADD_CALLINFO: + - start|ROUTE_ADD_CALLINFO_CALLER_PRIMARY: + - return|ROUTE_ADD_CALLINFO_CALLER_PRIMARY: + - start|ROUTE_ADD_CALLINFO_CALLEE_PRIMARY: + - return|ROUTE_ADD_CALLINFO_CALLEE_PRIMARY: + - return|ROUTE_ADD_CALLINFO: + - return|BRANCH_ROUTE_NO_SBC: + - return|BRANCH_ROUTE_NO_SBC: + - exit|ROUTE_OUTBOUND: +sip_in: + - '^INVITE' + - 'Contact: sip:testuser1002@' + - 'CSeq: 2 INVITE' + - 'Max-Forwards: 69' + - 'Content-Type: application/sdp' + - 'Proxy-Authorization: Digest username="testuser1002"' +sip_out: + - [ + '^SIP/2.0 100 Trying', + 'CSeq: 2 INVITE', + 'From: ;ip=127.126.0.1;port=\d+;primary=4311002', + 'P-NGCP-Callee-Info: ;ip=127.0.0.1;port=5080;primary=4311002', + ] diff --git a/scenarios/invite_allowip_soundset/0004_test.yml.tt2 b/scenarios/invite_allowip_soundset/0004_test.yml.tt2 new file mode 100644 index 00000000..2b350702 --- /dev/null +++ b/scenarios/invite_allowip_soundset/0004_test.yml.tt2 @@ -0,0 +1,19 @@ +flow: + - start|REPLY_ROUTE_NAT: + - exit|REPLY_ROUTE_NAT: +sip_in: + - '^SIP/2.0 183 Progress' + - 'From: ' + - 'Content-Type: application/sdp' + - 'Content-Length: \d+' +sip_out: + - [ + '^SIP/2.0 183 Progress', + 'Contact: ', + 'Content-Type: application/sdp', + 'Content-Length: \d+', + 'P-Out-Socket: udp:127.0.0.1:5060' + ] diff --git a/scenarios/invite_allowip_soundset/0005_test.yml.tt2 b/scenarios/invite_allowip_soundset/0005_test.yml.tt2 new file mode 100644 index 00000000..2ef1f28d --- /dev/null +++ b/scenarios/invite_allowip_soundset/0005_test.yml.tt2 @@ -0,0 +1,33 @@ +flow: + - start|REPLY_ROUTE_NAT: + - start|FAILURE_ROUTE_EARLY_REJECT: + - start|ROUTE_STOP_RTPPROXY_BRANCH: + - start|ROUTE_RESTORE_CLUSTERSET: + - return|ROUTE_RESTORE_CLUSTERSET: + - return|ROUTE_STOP_RTPPROXY_BRANCH: + - exit|FAILURE_ROUTE_EARLY_REJECT: + - start|dialog:failed: + - return|dialog:failed: + $avp(lua_dlg_profile): None + - return|dialog:failed: +sip_in: + - '^SIP/2.0 403 Unauthorized IP detected' + - 'From: ;tag=' + - 'To: ;tag=' + - 'CSeq: 2 INVITE' + - 'Content-Length: 0' +sip_out: + - [ + '^ACK sip:earlyannounce@app.local SIP/2.0', + 'From: ;tag=', + 'To: ;tag=', + 'CSeq: 2 ACK', + 'Max-Forwards: 68', + 'Content-Length: 0' + ] + - [ + '^SIP/2.0 403 Unauthorized IP detected', + 'CSeq: 2 INVITE', + 'Content-Length: 0', + 'P-Out-Socket: udp:127.0.0.1:5060' + ] diff --git a/scenarios/invite_allowip_soundset/0006_test.yml.tt2 b/scenarios/invite_allowip_soundset/0006_test.yml.tt2 new file mode 100644 index 00000000..758766c5 --- /dev/null +++ b/scenarios/invite_allowip_soundset/0006_test.yml.tt2 @@ -0,0 +1,23 @@ +flow: + - start|DEFAULT_ROUTE: + - start|ROUTE_NET_INFO: + - return|ROUTE_NET_INFO: + - start|ROUTE_PRX_REQUEST: + - start|ROUTE_INITVARS: + - return|ROUTE_INITVARS: + - start|ROUTE_LOCAL: + - return|ROUTE_LOCAL: +sip_in: + - '^ACK sip:testuser1003@spce.test:5060 SIP/2.0' + - 'From: ;tag=' + - 'To: ;tag=' + - 'CSeq: 2 ACK' + - 'Contact: sip:testuser1002@127.126.0.1:\d+' + - 'Max-Forwards: 69' + - 'Content-Length: 0' + - 'P-NGCP-Src-Ip: 127.126.0.1' + - 'P-NGCP-Src-Port: \d+' + - 'P-NGCP-Src-Proto: udp' + - 'P-NGCP-Src-Af: 4' + - 'P-Sock-Info: udp:127.0.0.1:5060' +sip_out: [] diff --git a/scenarios/invite_allowip_soundset/prefs.json b/scenarios/invite_allowip_soundset/prefs.json new file mode 100644 index 00000000..c18696fb --- /dev/null +++ b/scenarios/invite_allowip_soundset/prefs.json @@ -0,0 +1,11 @@ +{ + "@spce.test": { + "sound_set": "default_soundset" + }, + "testuser1002@spce.test": { + "allowed_ips": [ + "1.2.3.4" + ], + "cli": 4311002 + } +} diff --git a/scenarios/invite_allowip_soundset/scenario.yml b/scenarios/invite_allowip_soundset/scenario.yml new file mode 100644 index 00000000..3f131b79 --- /dev/null +++ b/scenarios/invite_allowip_soundset/scenario.yml @@ -0,0 +1,38 @@ +test_uuid: invite_allowip_soundset +domains: + 'spce.test': + reseller_id: 1 +customers: + 'customer.test': + contacts: + - email: "customer.test@spce.test" + reseller_id: 1 + details: + status: 'active' + type: 'sipaccount' + billing_profile_id: 1 + reseller_id: 1 +subscribers: + spce.test: + testuser1003: + customer: 'customer.test' + password: testuser + cc: 43 + ac: 1 + sn: 1003 + testuser1002: + customer: 'customer.test' + password: testuser + cc: 43 + ac: 1 + sn: 1002 +scenarios: + - ip: 127.126.0.1 + username: testuser1002 + domain: spce.test + responders: + - ip: 127.1.0.1 + username: testuser1003 + domain: spce.test + register: no + active: no diff --git a/scenarios/invite_allowip_soundset/sipp_scenario00.xml b/scenarios/invite_allowip_soundset/sipp_scenario00.xml new file mode 100644 index 00000000..9820fc2f --- /dev/null +++ b/scenarios/invite_allowip_soundset/sipp_scenario00.xml @@ -0,0 +1,110 @@ + + + + + ;tag=[pid]SIPpTag00[call_number] + To: + Call-ID: NGCP%[field4 file="callee.csv" line=0]%///[call_id] + CSeq: 1 INVITE + Contact: sip:[field0 file="caller.csv" line=0]@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio [media_port] RTP/AVP 8 + a=rtpmap:8 PCMA/8000 + a=ptime:50 + + ]]> + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: [peer_tag_param] + Call-ID: NGCP%[field4 file="callee.csv" line=0]%///[call_id] + CSeq: 1 ACK + Contact: sip:[field0 file="caller.csv" line=0]@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: + Call-ID: NGCP%[field4 file="callee.csv" line=0]%///[call_id] + CSeq: 2 INVITE + Contact: sip:[field0 file="caller.csv" line=0]@[local_ip]:[local_port] + Max-Forwards: 70 + [field1 file="caller.csv" line=0] + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio [media_port] RTP/AVP 8 + a=rtpmap:8 PCMA/8000 + a=ptime:50 + + ]]> + + + + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: [peer_tag_param] + Call-ID: NGCP%[field4 file="callee.csv" line=0]%///[call_id] + CSeq: 2 ACK + Contact: sip:[field0 file="caller.csv" line=0]@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + diff --git a/scenarios/invite_allowip_soundset/soundsets.yml b/scenarios/invite_allowip_soundset/soundsets.yml new file mode 100644 index 00000000..b22ee0e3 --- /dev/null +++ b/scenarios/invite_allowip_soundset/soundsets.yml @@ -0,0 +1,7 @@ +soundsets: + 'default_soundset': + reseller_id: 1 + sounds: + unauth_caller_ip: + filename: sounds/no_sh.wav + loopplay: false diff --git a/sounds/no_sh.wav b/sounds/no_sh.wav new file mode 100644 index 0000000000000000000000000000000000000000..5c9471abec34d0c8ea937332e3e0872da17d22be GIT binary patch literal 13016 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 Pl&0n3*RTJ7E%1K;a}!2h literal 0 HcmV?d00001