From 160c7979c44a91ef5118e0b4adcee5a455ad5f3a Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 15 Dec 2024 13:25:23 +0200 Subject: [PATCH] fixes --- app/admin/routing/customers_auths.rb | 39 +- app/models/customers_auth.rb | 4 + app/models/customers_auth_normalized.rb | 2 + app/models/disconnect_code.rb | 1 + app/models/gateway.rb | 13 +- app/models/importing/customers_auth.rb | 8 +- db/migrate/20241213172819_switch22_schema.rb | 35 - .../20241213175248_switch22_functions.rb | 147 +- db/seeds/main/class4.sql | 1 + db/structure.sql | 216 ++- spec/factories/customers_auths.rb | 2 + spec/factories/importing/customers_auths.rb | 6 +- spec/models/customers_auth_normalized_spec.rb | 2 + spec/models/customers_auth_spec.rb | 2 + spec/sql/switch22/route_spec.rb | 1277 ++++++++++++++++- 15 files changed, 1532 insertions(+), 223 deletions(-) diff --git a/app/admin/routing/customers_auths.rb b/app/admin/routing/customers_auths.rb index 7ab0a8369..f43be4328 100644 --- a/app/admin/routing/customers_auths.rb +++ b/app/admin/routing/customers_auths.rb @@ -45,7 +45,7 @@ :send_billing_information, :diversion_policy_name, :diversion_rewrite_rule, :diversion_rewrite_result, - :pai_policy_name, + :pai_policy_name, :pai_rewrite_rule, :pai_rewrite_result, [:src_number_field_name, proc { |row| row.src_number_field.try(:name) }], [:src_name_field_name, proc { |row| row.src_name_field.try(:name) }], [:dst_number_field_name, proc { |row| row.dst_number_field.try(:name) }], @@ -74,7 +74,7 @@ permit_params :name, :enabled, :reject_calls, :customer_id, :rateplan_id, :routing_plan_id, :gateway_id, :require_incoming_auth, :account_id, :check_account_balance, :diversion_policy_id, :diversion_rewrite_rule, :diversion_rewrite_result, - :pai_policy_id, + :pai_policy_id, :pai_rewrite_rule, :pai_rewrite_result, :src_name_rewrite_rule, :src_name_rewrite_result, :src_rewrite_rule, :src_rewrite_result, :dst_rewrite_rule, :dst_rewrite_result, @@ -317,11 +317,6 @@ def update scope: Routing::Numberlist.order(:name), path: '/numberlists/search' f.input :dump_level_id, as: :select, include_blank: false, collection: CustomersAuth::DUMP_LEVELS.invert - f.input :privacy_mode_id, - as: :select, - include_blank: false, - collection: CustomersAuth::PRIVACY_MODES.invert, - input_html: { class: :chosen } f.input :enable_audio_recording f.input :capacity f.input :cps_limit @@ -349,22 +344,38 @@ def update tab :number_translation do f.inputs do - f.input :diversion_policy_id, as: :select, include_blank: false, collection: CustomersAuth::DIVERSION_POLICIES.invert + f.input :privacy_mode_id, + as: :select, + include_blank: false, + collection: CustomersAuth::PRIVACY_MODES.invert, + input_html: { class: :chosen } + + f.input :diversion_policy_id, + as: :select, + include_blank: false, + collection: CustomersAuth::DIVERSION_POLICIES.invert, + input_html: { class: :chosen } f.input :diversion_rewrite_rule f.input :diversion_rewrite_result f.input :src_numberlist_use_diversion - f.input :pai_policy_id, as: :select, include_blank: false, collection: CustomersAuth::PAI_POLICIES.invert + f.input :pai_policy_id, + as: :select, + include_blank: false, + collection: CustomersAuth::PAI_POLICIES.invert, + input_html: { class: :chosen } + f.input :pai_rewrite_rule + f.input :pai_rewrite_result - f.input :src_name_field, as: :select, include_blank: false + f.input :src_name_field, as: :select, include_blank: false, input_html: { class: :chosen } f.input :src_name_rewrite_rule f.input :src_name_rewrite_result - f.input :src_number_field, as: :select, include_blank: false + f.input :src_number_field, as: :select, include_blank: false, input_html: { class: :chosen } f.input :src_rewrite_rule f.input :src_rewrite_result - f.input :dst_number_field, as: :select, include_blank: false + f.input :dst_number_field, as: :select, include_blank: false, input_html: { class: :chosen } f.input :dst_rewrite_rule f.input :dst_rewrite_result f.input :lua_script, input_html: { class: 'chosen' }, include_blank: 'None' @@ -438,7 +449,6 @@ def update row :src_numberlist row :dump_level, &:dump_level_name - row :privacy_mode_id, &:privacy_mode_name row :enable_audio_recording row :capacity row :cps_limit @@ -466,12 +476,15 @@ def update end tab :number_translation do attributes_table do + row :privacy_mode_id, &:privacy_mode_name row :diversion_policy, &:diversion_policy_name row :diversion_rewrite_rule row :diversion_rewrite_result row :src_numberlist_use_diversion row :pai_policy, &:pai_policy_name + row :pai_rewrite_rule + row :pai_rewrite_result row :src_name_field row :src_name_rewrite_rule diff --git a/app/models/customers_auth.rb b/app/models/customers_auth.rb index 35fffcb1e..6a600f7a4 100644 --- a/app/models/customers_auth.rb +++ b/app/models/customers_auth.rb @@ -25,6 +25,8 @@ # interface :string default([]), not null, is an Array # ip :inet default(["\"127.0.0.0/8\""]), is an Array # name :string not null +# pai_rewrite_result :string +# pai_rewrite_rule :string # reject_calls :boolean default(FALSE), not null # require_incoming_auth :boolean default(FALSE), not null # send_billing_information :boolean default(FALSE), not null @@ -338,9 +340,11 @@ def ss_invalid_identity_action_name def ss_no_identity_action_name ss_no_identity_action_id.nil? ? nil : SS_NO_IDENTITY_ACTIONS[ss_no_identity_action_id] end + def pai_policy_name PAI_POLICIES[pai_policy_id] end + def diversion_policy_name DIVERSION_POLICIES[diversion_policy_id] end diff --git a/app/models/customers_auth_normalized.rb b/app/models/customers_auth_normalized.rb index 0fdcb84e0..bbab3979c 100644 --- a/app/models/customers_auth_normalized.rb +++ b/app/models/customers_auth_normalized.rb @@ -25,6 +25,8 @@ # interface :string # ip :inet not null # name :string not null +# pai_rewrite_result :string +# pai_rewrite_rule :string # reject_calls :boolean default(FALSE), not null # require_incoming_auth :boolean default(FALSE), not null # send_billing_information :boolean default(FALSE), not null diff --git a/app/models/disconnect_code.rb b/app/models/disconnect_code.rb index eaf89acc3..24f6f6bc2 100644 --- a/app/models/disconnect_code.rb +++ b/app/models/disconnect_code.rb @@ -59,6 +59,7 @@ def display_name DC_NO_DESTINATION_WITH_APPROPRIATE_RATE = 8006 DC_IDENTITY_REQUIRED = 8018 DC_IDENTITY_INVALID = 8019 + DC_PAI_REQUIRED = 8020 def namespace_name NSS[namespace_id] diff --git a/app/models/gateway.rb b/app/models/gateway.rb index fc8724d6e..1fbdecbec 100644 --- a/app/models/gateway.rb +++ b/app/models/gateway.rb @@ -180,8 +180,9 @@ class Gateway < ApplicationRecord PAI_SEND_MODE_BUILD_SIP = 2 PAI_SEND_MODE_BUILD_SIP_WITH_USER_PHONE = 3 PAI_SEND_MODE_RELAY = 4 - PAI_SEND_MODE_RELAY_AS_TEL = 5, + PAI_SEND_MODE_RELAY_AS_TEL = 5 PAI_SEND_MODE_RELAY_AS_SIP = 6 + PAI_SEND_MODE_RELAY_AS_SIP_FORCE_DOMAIN = 7 PAI_SEND_MODES = { PAI_SEND_MODE_NO_SEND => 'Do not send', PAI_SEND_MODE_BUILD_TEL => 'Build TEL URI from Source Number', @@ -190,15 +191,16 @@ class Gateway < ApplicationRecord PAI_SEND_MODE_RELAY => 'Relay PAI/PPI as is', PAI_SEND_MODE_RELAY_AS_TEL => 'Relay PAI/PPI as TEL uri', PAI_SEND_MODE_RELAY_AS_SIP => 'Relay PAI/PPI as SIP uri', + PAI_SEND_MODE_RELAY_AS_SIP_FORCE_DOMAIN => 'Relay PAI/PPI as SIP uri. Replace domain' }.freeze REGISTERED_AOR_MODE_NO_USE = 0 REGISTERED_AOR_MODE_AS_IS = 1 REGISTERED_AOR_MODE_REPLACE_USERPART = 2 REGISTERED_AOR_MODES = { - PAI_SEND_MODE_NO_SEND => 'Do not use', - PAI_SEND_MODE_BUILD_TEL => 'Use AOR as is', - PAI_SEND_MODE_BUILD_SIP => 'Use AOR, replace userpart with dst number' + REGISTERED_AOR_MODE_NO_USE => 'Do not use', + REGISTERED_AOR_MODE_AS_IS => 'Use AOR as is', + REGISTERED_AOR_MODE_REPLACE_USERPART => 'Use AOR, replace userpart with dst number' }.freeze STIR_SHAKEN_MODE_DISABLE = 0 @@ -322,7 +324,8 @@ def normalize_host(value) presence: true, if: proc { pai_send_mode_id in [ - PAI_SEND_MODE_BUILD_SIP, PAI_SEND_MODE_BUILD_SIP_WITH_USER_PHONE, PAI_SEND_MODE_RELAY_AS_SIP + PAI_SEND_MODE_BUILD_SIP, PAI_SEND_MODE_BUILD_SIP_WITH_USER_PHONE, + PAI_SEND_MODE_RELAY_AS_SIP, PAI_SEND_MODE_RELAY_AS_SIP_FORCE_DOMAIN ] } diff --git a/app/models/importing/customers_auth.rb b/app/models/importing/customers_auth.rb index 52711cce1..3981958de 100644 --- a/app/models/importing/customers_auth.rb +++ b/app/models/importing/customers_auth.rb @@ -35,6 +35,9 @@ # max_dst_number_length :integer(2) # min_dst_number_length :integer(2) # name :string +# pai_policy_name :string +# pai_rewrite_result :string +# pai_rewrite_rule :string # pop_name :string # privacy_mode_name :string # radius_accounting_profile_name :string @@ -66,13 +69,14 @@ # x_yeti_auth :string # account_id :integer(4) # customer_id :integer(4) -# diversion_policy_id :integer(4) +# diversion_policy_id :integer(2) # dst_number_field_id :integer(2) # dst_numberlist_id :integer(4) # dump_level_id :integer(4) # gateway_id :integer(4) # lua_script_id :integer(2) # o_id :bigint(8) +# pai_policy_id :integer(2) # pop_id :integer(4) # privacy_mode_id :integer(2) # radius_accounting_profile_id :integer(2) @@ -160,9 +164,11 @@ class Importing::CustomersAuth < Importing::Base def dump_level_display_name dump_level_id.nil? ? 'unknown' : CustomersAuth::DUMP_LEVELS[dump_level_id] end + def diversion_policy_display_name diversion_policy_id.nil? ? 'unknown' : CustomersAuth::DIVERSION_POLICIES[diversion_policy_id] end + def pai_policy_display_name pai_policy_id.nil? ? 'unknown' : CustomersAuth::PAI_POLICIES[pai_policy_id] end diff --git a/db/migrate/20241213172819_switch22_schema.rb b/db/migrate/20241213172819_switch22_schema.rb index 82a309083..2a9aedabf 100644 --- a/db/migrate/20241213172819_switch22_schema.rb +++ b/db/migrate/20241213172819_switch22_schema.rb @@ -301,41 +301,6 @@ def up ); -CREATE FUNCTION switch22.build_uri(i_canonical boolean, i_schema character varying, i_display_name character varying, i_username character varying, i_username_params character varying[], i_domain character varying, i_port integer, i_uri_params character varying[]) RETURNS character varying - LANGUAGE plpgsql STABLE SECURITY DEFINER COST 10 - AS $$ -DECLARE - v_domainport varchar; - v_username varchar; - v_uri varchar; -BEGIN - - if coalesce(cardinality(i_username_params),0) >0 then - v_username = i_username||';'||array_to_string(i_username_params,';'); - else - v_username = i_username; - end if; - - -- adding username, domain and port. Username and port are optional - v_uri = COALESCE(v_username||'@','')||i_domain||COALESCE(':'||i_port::varchar,''); - - -- adding params after domainport if exists - if coalesce(cardinality(i_uri_params),0)>0 then - v_uri = v_uri||';'||array_to_string(i_uri_params,';'); - end if; - - if i_canonical then - v_uri = i_schema||':'||v_uri; - else - v_uri = COALESCE(i_display_name||' ','')||'<'||i_schema||':'||v_uri||'>'; - end if; - - return v_uri; -END; -$$; - - - CREATE FUNCTION switch22.check_event(i_event_id integer) RETURNS boolean LANGUAGE plpgsql COST 10 AS $$ diff --git a/db/migrate/20241213175248_switch22_functions.rb b/db/migrate/20241213175248_switch22_functions.rb index be34b8b73..9b9f60cce 100644 --- a/db/migrate/20241213175248_switch22_functions.rb +++ b/db/migrate/20241213175248_switch22_functions.rb @@ -6,12 +6,29 @@ def up drop table class4.diversion_policy; - alter table class4.customers_auth add pai_policy_id smallint not null default 1; -- accept by default - alter table class4.customers_auth_normalized add pai_policy_id smallint not null default 1; -- accept by default + alter table class4.customers_auth + add pai_policy_id smallint not null default 1, + add pai_rewrite_rule varchar, + add pai_rewrite_result varchar; + + alter table class4.customers_auth_normalized + add pai_policy_id smallint not null default 1, + add pai_rewrite_rule varchar, + add pai_rewrite_result varchar; alter table class4.customers_auth alter column diversion_policy_id type smallint; alter table class4.customers_auth_normalized alter column diversion_policy_id type smallint; + alter table data_import.import_customers_auth + add pai_policy_id smallint, + add pai_policy_name varchar, + add pai_rewrite_rule varchar, + add pai_rewrite_result varchar; + + alter table data_import.import_customers_auth alter column diversion_policy_id type smallint; + + INSERT INTO class4.disconnect_code (id, namespace_id, stop_hunting, pass_reason_to_originator, code, reason, rewrited_code, rewrited_reason, success, successnozerolen, store_cdr, silently_drop) VALUES (8020, 0, true, true, 403, 'PAI header required', NULL, NULL, false, false, true, false); + create type switch22.uri_ty as ( s varchar, n varchar, @@ -25,7 +42,6 @@ def up -- Diversion: test2 ;nparam1=nval1 - CREATE OR REPLACE FUNCTION switch22.build_uri( i_canonical boolean, i_schema character varying, @@ -34,7 +50,9 @@ def up i_username_params character varying[], i_domain character varying, i_port integer, - i_uri_params character varying[] + i_uri_params character varying[], + i_uri_headers character varying[] default '{}'::varchar[], + i_header_params character varying[] default '{}'::varchar[] ) RETURNS character varying LANGUAGE plpgsql STABLE SECURITY DEFINER COST 10 AS $$ @@ -43,28 +61,41 @@ def up v_username varchar; v_uri varchar; BEGIN - - if coalesce(cardinality(i_username_params),0) >0 then - v_username = i_username||';'||array_to_string(i_username_params,';'); + if i_schema = 'tel' then + v_uri = 'tel:'||i_username; + -- adding params after number if exists + if coalesce(cardinality(i_uri_params),0)>0 then + v_uri = v_uri||';'||array_to_string(i_uri_params,';'); + end if; + v_uri = '<'||v_uri||'>'; else - v_username = i_username; - end if; + -- sip or sips + if coalesce(cardinality(i_username_params),0) >0 then + v_username = i_username||';'||array_to_string(i_username_params,';'); + else + v_username = i_username; + end if; - -- adding username, domain and port. Username and port are optional - v_uri = COALESCE(v_username||'@','')||i_domain||COALESCE(':'||i_port::varchar,''); + -- adding username, domain and port. Username and port are optional + v_uri = COALESCE(v_username||'@','')||i_domain||COALESCE(':'||i_port::varchar,''); - -- adding params after domainport if exists - if coalesce(cardinality(i_uri_params),0)>0 then - v_uri = v_uri||';'||array_to_string(i_uri_params,';'); + -- adding params after domainport if exists + if coalesce(cardinality(i_uri_params),0)>0 then + v_uri = v_uri||';'||array_to_string(i_uri_params,';'); + end if; + + if i_canonical then + v_uri = i_schema||':'||v_uri; + else + v_uri = '<'||i_schema||':'||v_uri||'>'; + IF i_display_name is not null and i_display_name!='' THEN + v_uri = '"'||i_display_name||'" '||v_uri; + END IF; + end if; end if; - if i_canonical then - v_uri = i_schema||':'||v_uri; - else - v_uri = '<'||i_schema||':'||v_uri||'>'; - IF i_display_name is not null and i_display_name!='' THEN - v_uri = '"'||i_display_name||'" '||v_uri; - END IF; + if cardinality(i_header_params) > 0 then + v_uri = v_uri||';'||array_to_string(i_header_params,';'); end if; return v_uri; @@ -80,7 +111,7 @@ def up v_username varchar; v_uri varchar; BEGIN - return switch22.build_uri(i_canonical, i_data.s, i_data.n, i_data.u, '{}'::varchar[], i_data.h, i_data.p, '{}'::varchar[]); + return switch22.build_uri(i_canonical, i_data.s, i_data.n, i_data.u, '{}'::varchar[], i_data.h, i_data.p, i_data.up_arr, i_data.uh_arr, i_data.np_arr); END; $$; @@ -173,7 +204,7 @@ def up v_lua_context switch22.lua_call_context; v_identity_data switch22.identity_data_ty[]; v_identity_record switch22.identity_data_ty; - v_pai switch22.uri_ty[]; + v_pai switch22.uri_ty[] not null default ARRAY[]::switch22.uri_ty[]; v_ppi switch22.uri_ty; v_privacy varchar[]; v_diversion switch22.uri_ty[] not null default ARRAY[]::switch22.uri_ty[]; @@ -232,14 +263,6 @@ def up v_ret.from_domain=i_from_domain; v_ret.to_domain=i_to_domain; - select into v_pai array_agg(d) from json_populate_recordset(null::switch22.uri_ty, i_pai) d WHERE d.u is not null and d.u!=''; - v_pai = COALESCE(v_pai, ARRAY[]::switch22.uri_ty[]); - - v_ppi = json_populate_record(null::switch22.uri_ty, i_ppi); - if v_ppi.u is null then - v_ppi = null; - end if; - v_privacy = string_to_array(COALESCE(i_privacy,''),';'); /*dbg{*/ @@ -426,6 +449,17 @@ def up END LOOP; END IF; + IF v_customer_auth_normalized.pai_policy_id > 0 THEN /* accept or require */ + -- PAI without userpart is useless + select into v_pai COALESCE(array_agg(d), ARRAY[]::switch22.uri_ty[]) from json_populate_recordset(null::switch22.uri_ty, i_pai) d WHERE d.u is not null and d.u!=''; + + -- PPI without userpart is useless + v_ppi = json_populate_record(null::switch22.uri_ty, i_ppi); + if v_ppi.u is null then + v_ppi = null; + end if; + END IF; + -- feel customer data ;-) v_ret.dump_level_id:=v_customer_auth_normalized.dump_level_id; v_ret.customer_auth_id:=v_customer_auth_normalized.customers_auth_id; @@ -571,6 +605,12 @@ def up v_ret.customer_acc_external_id=v_c_acc.external_id; v_ret.customer_acc_vat=v_c_acc.vat; + IF v_customer_auth_normalized.pai_policy_id = 2 AND cardinality(v_pai) = 0 THEN + v_ret.disconnect_code_id = 8020; -- PAI header required; + RETURN NEXT v_ret; + RETURN; + END IF; + v_ret.lega_res=''; if v_customer_auth_normalized.capacity is not null then v_ret.lega_res='3:'||v_customer_auth_normalized.customers_auth_id||':'||v_customer_auth_normalized.capacity::varchar||':1;'; @@ -790,7 +830,7 @@ def up if v_customer_auth_normalized.src_numberlist_use_diversion AND v_diversion[1].u is not null then /*dbg{*/ v_end:=clock_timestamp(); - RAISE NOTICE '% ms -> SRC Numberlist processing. Lookup by key %, fallback to %', EXTRACT(MILLISECOND from v_end-v_start), v_ret.src_prefix_out, v_diversion[1]; + RAISE NOTICE '% ms -> SRC Numberlist processing. Lookup by key %, fallback to %', EXTRACT(MILLISECOND from v_end-v_start), v_ret.src_prefix_out, v_diversion[1].u; /*}dbg*/ v_numberlist_item=switch22.match_numberlist(v_customer_auth_normalized.src_numberlist_id, v_ret.src_prefix_out, v_diversion[1].u); else @@ -2161,22 +2201,24 @@ def up /* Diversion as SIP URI */ FOREACH v_diversion_header IN ARRAY i_diversion LOOP v_diversion_header.u = yeti_ext.regexp_replace_rand(v_diversion_header.u, i_vendor_gw.diversion_rewrite_rule, i_vendor_gw.diversion_rewrite_result); + v_diversion_header.s = 'sip'; + v_diversion_header.h = i_vendor_gw.diversion_domain; v_bleg_append_headers_req = array_append( v_bleg_append_headers_req, - format('Diversion: ', v_diversion_header.u, i_vendor_gw.diversion_domain)::varchar + 'Diversion: '||switch22.build_uri(false, v_diversion_header) ); END LOOP; ELSIF i_vendor_gw.diversion_send_mode_id = 3 THEN /* Diversion as TEL URI */ FOREACH v_diversion_header IN ARRAY i_diversion LOOP v_diversion_header.u = yeti_ext.regexp_replace_rand(v_diversion_header.u, i_vendor_gw.diversion_rewrite_rule, i_vendor_gw.diversion_rewrite_result); + v_diversion_header.s = 'tel'; v_bleg_append_headers_req=array_append( v_bleg_append_headers_req, - format('Diversion: ', v_diversion_header.u)::varchar + 'Diversion: '||switch22.build_uri(false, v_diversion_header) ); END LOOP; END IF; - END IF; CASE i_vendor_gw.privacy_mode_id @@ -2274,7 +2316,19 @@ def up END LOOP; IF i_ppi.u is not null THEN i_ppi.s = 'sip'; - i_ppi.s = COALESCE(i_ppi.h, i_vendor_gw.pai_domain); + i_ppi.h = COALESCE(i_ppi.h, i_vendor_gw.pai_domain); + v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Preferred-Identity: %s', switch22.build_uri(false, i_ppi))::varchar); + END IF; + ELSIF i_vendor_gw.pai_send_mode_id = 7 THEN + -- relay with conversion to SIP URI. Force replace domain + FOREACH v_pai IN ARRAY i_pai LOOP + v_pai.s = 'sip'; + v_pai.h = i_vendor_gw.pai_domain; + v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Asserted-Identity: %s', switch22.build_uri(false, v_pai))::varchar); + END LOOP; + IF i_ppi.u is not null THEN + i_ppi.s = 'sip'; + i_ppi.h = i_vendor_gw.pai_domain; v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Preferred-Identity: %s', switch22.build_uri(false, i_ppi))::varchar); END IF; END IF; @@ -2712,8 +2766,21 @@ def up def down execute %q{ - alter table class4.customers_auth drop column pai_policy_id; - alter table class4.customers_auth_normalized drop column pai_policy_id; + alter table class4.customers_auth + drop column pai_policy_id, + drop column pai_rewrite_rule, + drop column pai_rewrite_result; + + alter table class4.customers_auth_normalized + drop column pai_policy_id, + drop column pai_rewrite_rule, + drop column pai_rewrite_result; + + alter table data_import.import_customers_auth + drop column pai_policy_id, + drop column pai_policy_name, + drop column pai_rewrite_rule, + drop column pai_rewrite_result; create table class4.diversion_policy ( id integer primary key, @@ -2726,8 +2793,12 @@ def down alter table class4.customers_auth alter column diversion_policy_id type integer; alter table class4.customers_auth_normalized alter column diversion_policy_id type integer; + alter table data_import.import_customers_auth alter column diversion_policy_id type integer; + alter table class4.customers_auth add CONSTRAINT "customers_auth_diversion_policy_id_fkey" FOREIGN KEY (diversion_policy_id) REFERENCES class4.diversion_policy(id); + delete from class4.disconnect_code WHERE id=8020; + } end diff --git a/db/seeds/main/class4.sql b/db/seeds/main/class4.sql index 9bea5449e..7e672babb 100644 --- a/db/seeds/main/class4.sql +++ b/db/seeds/main/class4.sql @@ -350,6 +350,7 @@ INSERT INTO disconnect_code (id, namespace_id, stop_hunting, pass_reason_to_orig INSERT INTO disconnect_code (id, namespace_id, stop_hunting, pass_reason_to_originator, code, reason, rewrited_code, rewrited_reason, success, successnozerolen, store_cdr, silently_drop) VALUES (8017, 0, true, true, 403, 'Source number blacklisted by routing plan', NULL, NULL, false, false, true, false); INSERT INTO disconnect_code (id, namespace_id, stop_hunting, pass_reason_to_originator, code, reason, rewrited_code, rewrited_reason, success, successnozerolen, store_cdr, silently_drop) VALUES (8018, 0, true, true, 403, 'Identity required', NULL, NULL, false, false, true, false); INSERT INTO disconnect_code (id, namespace_id, stop_hunting, pass_reason_to_originator, code, reason, rewrited_code, rewrited_reason, success, successnozerolen, store_cdr, silently_drop) VALUES (8019, 0, true, true, 403, 'Identity invalid', NULL, NULL, false, false, true, false); +INSERT INTO disconnect_code (id, namespace_id, stop_hunting, pass_reason_to_originator, code, reason, rewrited_code, rewrited_reason, success, successnozerolen, store_cdr, silently_drop) VALUES (8020, 0, true, true, 403, 'PAI header required', NULL, NULL, false, false, true, false); INSERT INTO disconnect_code (id, namespace_id, stop_hunting, pass_reason_to_originator, code, reason, rewrited_code, rewrited_reason, success, successnozerolen, store_cdr, silently_drop) VALUES (1505, 1, false, false, 487, 'Ringing timeout', NULL, NULL, false, false, true, false); INSERT INTO disconnect_code (id, namespace_id, stop_hunting, pass_reason_to_originator, code, reason, rewrited_code, rewrited_reason, success, successnozerolen, store_cdr, silently_drop) VALUES (2001, 3, true, false, 503, 'Radius response timeout', NULL, NULL, false, false, true, false); diff --git a/db/structure.sql b/db/structure.sql index 8c57bf337..4b4af679c 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -31278,16 +31278,16 @@ DECLARE v_username varchar; v_uri varchar; BEGIN - return switch22.build_uri(i_canonical, i_data.s, i_data.n, i_data.u, '{}'::varchar[], i_data.h, i_data.p, '{}'::varchar[]); + return switch22.build_uri(i_canonical, i_data.s, i_data.n, i_data.u, '{}'::varchar[], i_data.h, i_data.p, i_data.up_arr, i_data.uh_arr, i_data.np_arr); END; $$; -- --- Name: build_uri(boolean, character varying, character varying, character varying, character varying[], character varying, integer, character varying[]); Type: FUNCTION; Schema: switch22; Owner: - +-- Name: build_uri(boolean, character varying, character varying, character varying, character varying[], character varying, integer, character varying[], character varying[], character varying[]); Type: FUNCTION; Schema: switch22; Owner: - -- -CREATE FUNCTION switch22.build_uri(i_canonical boolean, i_schema character varying, i_display_name character varying, i_username character varying, i_username_params character varying[], i_domain character varying, i_port integer, i_uri_params character varying[]) RETURNS character varying +CREATE FUNCTION switch22.build_uri(i_canonical boolean, i_schema character varying, i_display_name character varying, i_username character varying, i_username_params character varying[], i_domain character varying, i_port integer, i_uri_params character varying[], i_uri_headers character varying[] DEFAULT '{}'::character varying[], i_header_params character varying[] DEFAULT '{}'::character varying[]) RETURNS character varying LANGUAGE plpgsql STABLE SECURITY DEFINER COST 10 AS $$ DECLARE @@ -31295,28 +31295,41 @@ DECLARE v_username varchar; v_uri varchar; BEGIN - - if coalesce(cardinality(i_username_params),0) >0 then - v_username = i_username||';'||array_to_string(i_username_params,';'); + if i_schema = 'tel' then + v_uri = 'tel:'||i_username; + -- adding params after number if exists + if coalesce(cardinality(i_uri_params),0)>0 then + v_uri = v_uri||';'||array_to_string(i_uri_params,';'); + end if; + v_uri = '<'||v_uri||'>'; else - v_username = i_username; - end if; + -- sip or sips + if coalesce(cardinality(i_username_params),0) >0 then + v_username = i_username||';'||array_to_string(i_username_params,';'); + else + v_username = i_username; + end if; - -- adding username, domain and port. Username and port are optional - v_uri = COALESCE(v_username||'@','')||i_domain||COALESCE(':'||i_port::varchar,''); + -- adding username, domain and port. Username and port are optional + v_uri = COALESCE(v_username||'@','')||i_domain||COALESCE(':'||i_port::varchar,''); - -- adding params after domainport if exists - if coalesce(cardinality(i_uri_params),0)>0 then - v_uri = v_uri||';'||array_to_string(i_uri_params,';'); + -- adding params after domainport if exists + if coalesce(cardinality(i_uri_params),0)>0 then + v_uri = v_uri||';'||array_to_string(i_uri_params,';'); + end if; + + if i_canonical then + v_uri = i_schema||':'||v_uri; + else + v_uri = '<'||i_schema||':'||v_uri||'>'; + IF i_display_name is not null and i_display_name!='' THEN + v_uri = '"'||i_display_name||'" '||v_uri; + END IF; + end if; end if; - if i_canonical then - v_uri = i_schema||':'||v_uri; - else - v_uri = '<'||i_schema||':'||v_uri||'>'; - IF i_display_name is not null and i_display_name!='' THEN - v_uri = '"'||i_display_name||'" '||v_uri; - END IF; + if cardinality(i_header_params) > 0 then + v_uri = v_uri||';'||array_to_string(i_header_params,';'); end if; return v_uri; @@ -32979,22 +32992,24 @@ BEGIN /* Diversion as SIP URI */ FOREACH v_diversion_header IN ARRAY i_diversion LOOP v_diversion_header.u = yeti_ext.regexp_replace_rand(v_diversion_header.u, i_vendor_gw.diversion_rewrite_rule, i_vendor_gw.diversion_rewrite_result); + v_diversion_header.s = 'sip'; + v_diversion_header.h = i_vendor_gw.diversion_domain; v_bleg_append_headers_req = array_append( v_bleg_append_headers_req, - format('Diversion: ', v_diversion_header.u, i_vendor_gw.diversion_domain)::varchar + 'Diversion: '||switch22.build_uri(false, v_diversion_header) ); END LOOP; ELSIF i_vendor_gw.diversion_send_mode_id = 3 THEN /* Diversion as TEL URI */ FOREACH v_diversion_header IN ARRAY i_diversion LOOP v_diversion_header.u = yeti_ext.regexp_replace_rand(v_diversion_header.u, i_vendor_gw.diversion_rewrite_rule, i_vendor_gw.diversion_rewrite_result); + v_diversion_header.s = 'tel'; v_bleg_append_headers_req=array_append( v_bleg_append_headers_req, - format('Diversion: ', v_diversion_header.u)::varchar + 'Diversion: '||switch22.build_uri(false, v_diversion_header) ); END LOOP; END IF; - END IF; CASE i_vendor_gw.privacy_mode_id @@ -33092,7 +33107,19 @@ BEGIN END LOOP; IF i_ppi.u is not null THEN i_ppi.s = 'sip'; - i_ppi.s = COALESCE(i_ppi.h, i_vendor_gw.pai_domain); + i_ppi.h = COALESCE(i_ppi.h, i_vendor_gw.pai_domain); + v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Preferred-Identity: %s', switch22.build_uri(false, i_ppi))::varchar); + END IF; + ELSIF i_vendor_gw.pai_send_mode_id = 7 THEN + -- relay with conversion to SIP URI. Force replace domain + FOREACH v_pai IN ARRAY i_pai LOOP + v_pai.s = 'sip'; + v_pai.h = i_vendor_gw.pai_domain; + v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Asserted-Identity: %s', switch22.build_uri(false, v_pai))::varchar); + END LOOP; + IF i_ppi.u is not null THEN + i_ppi.s = 'sip'; + i_ppi.h = i_vendor_gw.pai_domain; v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Preferred-Identity: %s', switch22.build_uri(false, i_ppi))::varchar); END IF; END IF; @@ -33763,22 +33790,24 @@ BEGIN /* Diversion as SIP URI */ FOREACH v_diversion_header IN ARRAY i_diversion LOOP v_diversion_header.u = yeti_ext.regexp_replace_rand(v_diversion_header.u, i_vendor_gw.diversion_rewrite_rule, i_vendor_gw.diversion_rewrite_result); + v_diversion_header.s = 'sip'; + v_diversion_header.h = i_vendor_gw.diversion_domain; v_bleg_append_headers_req = array_append( v_bleg_append_headers_req, - format('Diversion: ', v_diversion_header.u, i_vendor_gw.diversion_domain)::varchar + 'Diversion: '||switch22.build_uri(false, v_diversion_header) ); END LOOP; ELSIF i_vendor_gw.diversion_send_mode_id = 3 THEN /* Diversion as TEL URI */ FOREACH v_diversion_header IN ARRAY i_diversion LOOP v_diversion_header.u = yeti_ext.regexp_replace_rand(v_diversion_header.u, i_vendor_gw.diversion_rewrite_rule, i_vendor_gw.diversion_rewrite_result); + v_diversion_header.s = 'tel'; v_bleg_append_headers_req=array_append( v_bleg_append_headers_req, - format('Diversion: ', v_diversion_header.u)::varchar + 'Diversion: '||switch22.build_uri(false, v_diversion_header) ); END LOOP; END IF; - END IF; CASE i_vendor_gw.privacy_mode_id @@ -33876,7 +33905,19 @@ BEGIN END LOOP; IF i_ppi.u is not null THEN i_ppi.s = 'sip'; - i_ppi.s = COALESCE(i_ppi.h, i_vendor_gw.pai_domain); + i_ppi.h = COALESCE(i_ppi.h, i_vendor_gw.pai_domain); + v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Preferred-Identity: %s', switch22.build_uri(false, i_ppi))::varchar); + END IF; + ELSIF i_vendor_gw.pai_send_mode_id = 7 THEN + -- relay with conversion to SIP URI. Force replace domain + FOREACH v_pai IN ARRAY i_pai LOOP + v_pai.s = 'sip'; + v_pai.h = i_vendor_gw.pai_domain; + v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Asserted-Identity: %s', switch22.build_uri(false, v_pai))::varchar); + END LOOP; + IF i_ppi.u is not null THEN + i_ppi.s = 'sip'; + i_ppi.h = i_vendor_gw.pai_domain; v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Preferred-Identity: %s', switch22.build_uri(false, i_ppi))::varchar); END IF; END IF; @@ -34488,22 +34529,24 @@ BEGIN /* Diversion as SIP URI */ FOREACH v_diversion_header IN ARRAY i_diversion LOOP v_diversion_header.u = yeti_ext.regexp_replace_rand(v_diversion_header.u, i_vendor_gw.diversion_rewrite_rule, i_vendor_gw.diversion_rewrite_result); + v_diversion_header.s = 'sip'; + v_diversion_header.h = i_vendor_gw.diversion_domain; v_bleg_append_headers_req = array_append( v_bleg_append_headers_req, - format('Diversion: ', v_diversion_header.u, i_vendor_gw.diversion_domain)::varchar + 'Diversion: '||switch22.build_uri(false, v_diversion_header) ); END LOOP; ELSIF i_vendor_gw.diversion_send_mode_id = 3 THEN /* Diversion as TEL URI */ FOREACH v_diversion_header IN ARRAY i_diversion LOOP v_diversion_header.u = yeti_ext.regexp_replace_rand(v_diversion_header.u, i_vendor_gw.diversion_rewrite_rule, i_vendor_gw.diversion_rewrite_result); + v_diversion_header.s = 'tel'; v_bleg_append_headers_req=array_append( v_bleg_append_headers_req, - format('Diversion: ', v_diversion_header.u)::varchar + 'Diversion: '||switch22.build_uri(false, v_diversion_header) ); END LOOP; END IF; - END IF; CASE i_vendor_gw.privacy_mode_id @@ -34583,7 +34626,19 @@ BEGIN END LOOP; IF i_ppi.u is not null THEN i_ppi.s = 'sip'; - i_ppi.s = COALESCE(i_ppi.h, i_vendor_gw.pai_domain); + i_ppi.h = COALESCE(i_ppi.h, i_vendor_gw.pai_domain); + v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Preferred-Identity: %s', switch22.build_uri(false, i_ppi))::varchar); + END IF; + ELSIF i_vendor_gw.pai_send_mode_id = 7 THEN + -- relay with conversion to SIP URI. Force replace domain + FOREACH v_pai IN ARRAY i_pai LOOP + v_pai.s = 'sip'; + v_pai.h = i_vendor_gw.pai_domain; + v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Asserted-Identity: %s', switch22.build_uri(false, v_pai))::varchar); + END LOOP; + IF i_ppi.u is not null THEN + i_ppi.s = 'sip'; + i_ppi.h = i_vendor_gw.pai_domain; v_bleg_append_headers_req = array_append(v_bleg_append_headers_req, format('P-Preferred-Identity: %s', switch22.build_uri(false, i_ppi))::varchar); END IF; END IF; @@ -34926,7 +34981,7 @@ CREATE FUNCTION switch22.route(i_node_id integer, i_pop_id integer, i_protocol_i v_lua_context switch22.lua_call_context; v_identity_data switch22.identity_data_ty[]; v_identity_record switch22.identity_data_ty; - v_pai switch22.uri_ty[]; + v_pai switch22.uri_ty[] not null default ARRAY[]::switch22.uri_ty[]; v_ppi switch22.uri_ty; v_privacy varchar[]; v_diversion switch22.uri_ty[] not null default ARRAY[]::switch22.uri_ty[]; @@ -34985,14 +35040,6 @@ CREATE FUNCTION switch22.route(i_node_id integer, i_pop_id integer, i_protocol_i v_ret.from_domain=i_from_domain; v_ret.to_domain=i_to_domain; - select into v_pai array_agg(d) from json_populate_recordset(null::switch22.uri_ty, i_pai) d WHERE d.u is not null and d.u!=''; - v_pai = COALESCE(v_pai, ARRAY[]::switch22.uri_ty[]); - - v_ppi = json_populate_record(null::switch22.uri_ty, i_ppi); - if v_ppi.u is null then - v_ppi = null; - end if; - v_privacy = string_to_array(COALESCE(i_privacy,''),';'); /*dbg{*/ @@ -35179,6 +35226,17 @@ CREATE FUNCTION switch22.route(i_node_id integer, i_pop_id integer, i_protocol_i END LOOP; END IF; + IF v_customer_auth_normalized.pai_policy_id > 0 THEN /* accept or require */ + -- PAI without userpart is useless + select into v_pai COALESCE(array_agg(d), ARRAY[]::switch22.uri_ty[]) from json_populate_recordset(null::switch22.uri_ty, i_pai) d WHERE d.u is not null and d.u!=''; + + -- PPI without userpart is useless + v_ppi = json_populate_record(null::switch22.uri_ty, i_ppi); + if v_ppi.u is null then + v_ppi = null; + end if; + END IF; + -- feel customer data ;-) v_ret.dump_level_id:=v_customer_auth_normalized.dump_level_id; v_ret.customer_auth_id:=v_customer_auth_normalized.customers_auth_id; @@ -35324,6 +35382,12 @@ CREATE FUNCTION switch22.route(i_node_id integer, i_pop_id integer, i_protocol_i v_ret.customer_acc_external_id=v_c_acc.external_id; v_ret.customer_acc_vat=v_c_acc.vat; + IF v_customer_auth_normalized.pai_policy_id = 2 AND cardinality(v_pai) = 0 THEN + v_ret.disconnect_code_id = 8020; -- PAI header required; + RETURN NEXT v_ret; + RETURN; + END IF; + v_ret.lega_res=''; if v_customer_auth_normalized.capacity is not null then v_ret.lega_res='3:'||v_customer_auth_normalized.customers_auth_id||':'||v_customer_auth_normalized.capacity::varchar||':1;'; @@ -35543,7 +35607,7 @@ CREATE FUNCTION switch22.route(i_node_id integer, i_pop_id integer, i_protocol_i if v_customer_auth_normalized.src_numberlist_use_diversion AND v_diversion[1].u is not null then /*dbg{*/ v_end:=clock_timestamp(); - RAISE NOTICE '% ms -> SRC Numberlist processing. Lookup by key %, fallback to %', EXTRACT(MILLISECOND from v_end-v_start), v_ret.src_prefix_out, v_diversion[1]; + RAISE NOTICE '% ms -> SRC Numberlist processing. Lookup by key %, fallback to %', EXTRACT(MILLISECOND from v_end-v_start), v_ret.src_prefix_out, v_diversion[1].u; /*}dbg*/ v_numberlist_item=switch22.match_numberlist(v_customer_auth_normalized.src_numberlist_id, v_ret.src_prefix_out, v_diversion[1].u); else @@ -36569,7 +36633,7 @@ CREATE FUNCTION switch22.route_debug(i_node_id integer, i_pop_id integer, i_prot v_lua_context switch22.lua_call_context; v_identity_data switch22.identity_data_ty[]; v_identity_record switch22.identity_data_ty; - v_pai switch22.uri_ty[]; + v_pai switch22.uri_ty[] not null default ARRAY[]::switch22.uri_ty[]; v_ppi switch22.uri_ty; v_privacy varchar[]; v_diversion switch22.uri_ty[] not null default ARRAY[]::switch22.uri_ty[]; @@ -36628,14 +36692,6 @@ CREATE FUNCTION switch22.route_debug(i_node_id integer, i_pop_id integer, i_prot v_ret.from_domain=i_from_domain; v_ret.to_domain=i_to_domain; - select into v_pai array_agg(d) from json_populate_recordset(null::switch22.uri_ty, i_pai) d WHERE d.u is not null and d.u!=''; - v_pai = COALESCE(v_pai, ARRAY[]::switch22.uri_ty[]); - - v_ppi = json_populate_record(null::switch22.uri_ty, i_ppi); - if v_ppi.u is null then - v_ppi = null; - end if; - v_privacy = string_to_array(COALESCE(i_privacy,''),';'); /*dbg{*/ @@ -36822,6 +36878,17 @@ CREATE FUNCTION switch22.route_debug(i_node_id integer, i_pop_id integer, i_prot END LOOP; END IF; + IF v_customer_auth_normalized.pai_policy_id > 0 THEN /* accept or require */ + -- PAI without userpart is useless + select into v_pai COALESCE(array_agg(d), ARRAY[]::switch22.uri_ty[]) from json_populate_recordset(null::switch22.uri_ty, i_pai) d WHERE d.u is not null and d.u!=''; + + -- PPI without userpart is useless + v_ppi = json_populate_record(null::switch22.uri_ty, i_ppi); + if v_ppi.u is null then + v_ppi = null; + end if; + END IF; + -- feel customer data ;-) v_ret.dump_level_id:=v_customer_auth_normalized.dump_level_id; v_ret.customer_auth_id:=v_customer_auth_normalized.customers_auth_id; @@ -36967,6 +37034,12 @@ CREATE FUNCTION switch22.route_debug(i_node_id integer, i_pop_id integer, i_prot v_ret.customer_acc_external_id=v_c_acc.external_id; v_ret.customer_acc_vat=v_c_acc.vat; + IF v_customer_auth_normalized.pai_policy_id = 2 AND cardinality(v_pai) = 0 THEN + v_ret.disconnect_code_id = 8020; -- PAI header required; + RETURN NEXT v_ret; + RETURN; + END IF; + v_ret.lega_res=''; if v_customer_auth_normalized.capacity is not null then v_ret.lega_res='3:'||v_customer_auth_normalized.customers_auth_id||':'||v_customer_auth_normalized.capacity::varchar||':1;'; @@ -37186,7 +37259,7 @@ CREATE FUNCTION switch22.route_debug(i_node_id integer, i_pop_id integer, i_prot if v_customer_auth_normalized.src_numberlist_use_diversion AND v_diversion[1].u is not null then /*dbg{*/ v_end:=clock_timestamp(); - RAISE NOTICE '% ms -> SRC Numberlist processing. Lookup by key %, fallback to %', EXTRACT(MILLISECOND from v_end-v_start), v_ret.src_prefix_out, v_diversion[1]; + RAISE NOTICE '% ms -> SRC Numberlist processing. Lookup by key %, fallback to %', EXTRACT(MILLISECOND from v_end-v_start), v_ret.src_prefix_out, v_diversion[1].u; /*}dbg*/ v_numberlist_item=switch22.match_numberlist(v_customer_auth_normalized.src_numberlist_id, v_ret.src_prefix_out, v_diversion[1].u); else @@ -38209,7 +38282,7 @@ CREATE FUNCTION switch22.route_release(i_node_id integer, i_pop_id integer, i_pr v_lua_context switch22.lua_call_context; v_identity_data switch22.identity_data_ty[]; v_identity_record switch22.identity_data_ty; - v_pai switch22.uri_ty[]; + v_pai switch22.uri_ty[] not null default ARRAY[]::switch22.uri_ty[]; v_ppi switch22.uri_ty; v_privacy varchar[]; v_diversion switch22.uri_ty[] not null default ARRAY[]::switch22.uri_ty[]; @@ -38264,14 +38337,6 @@ CREATE FUNCTION switch22.route_release(i_node_id integer, i_pop_id integer, i_pr v_ret.from_domain=i_from_domain; v_ret.to_domain=i_to_domain; - select into v_pai array_agg(d) from json_populate_recordset(null::switch22.uri_ty, i_pai) d WHERE d.u is not null and d.u!=''; - v_pai = COALESCE(v_pai, ARRAY[]::switch22.uri_ty[]); - - v_ppi = json_populate_record(null::switch22.uri_ty, i_ppi); - if v_ppi.u is null then - v_ppi = null; - end if; - v_privacy = string_to_array(COALESCE(i_privacy,''),';'); @@ -38437,6 +38502,17 @@ CREATE FUNCTION switch22.route_release(i_node_id integer, i_pop_id integer, i_pr END LOOP; END IF; + IF v_customer_auth_normalized.pai_policy_id > 0 THEN /* accept or require */ + -- PAI without userpart is useless + select into v_pai COALESCE(array_agg(d), ARRAY[]::switch22.uri_ty[]) from json_populate_recordset(null::switch22.uri_ty, i_pai) d WHERE d.u is not null and d.u!=''; + + -- PPI without userpart is useless + v_ppi = json_populate_record(null::switch22.uri_ty, i_ppi); + if v_ppi.u is null then + v_ppi = null; + end if; + END IF; + -- feel customer data ;-) v_ret.dump_level_id:=v_customer_auth_normalized.dump_level_id; v_ret.customer_auth_id:=v_customer_auth_normalized.customers_auth_id; @@ -38576,6 +38652,12 @@ CREATE FUNCTION switch22.route_release(i_node_id integer, i_pop_id integer, i_pr v_ret.customer_acc_external_id=v_c_acc.external_id; v_ret.customer_acc_vat=v_c_acc.vat; + IF v_customer_auth_normalized.pai_policy_id = 2 AND cardinality(v_pai) = 0 THEN + v_ret.disconnect_code_id = 8020; -- PAI header required; + RETURN NEXT v_ret; + RETURN; + END IF; + v_ret.lega_res=''; if v_customer_auth_normalized.capacity is not null then v_ret.lega_res='3:'||v_customer_auth_normalized.customers_auth_id||':'||v_customer_auth_normalized.capacity::varchar||':1;'; @@ -40697,6 +40779,8 @@ CREATE TABLE class4.customers_auth ( ss_dst_rewrite_rule character varying, ss_dst_rewrite_result character varying, pai_policy_id smallint DEFAULT 1 NOT NULL, + pai_rewrite_rule character varying, + pai_rewrite_result character varying, CONSTRAINT ip_not_empty CHECK ((ip <> '{}'::inet[])) ); @@ -40804,6 +40888,8 @@ CREATE TABLE class4.customers_auth_normalized ( ss_dst_rewrite_rule character varying, ss_dst_rewrite_result character varying, pai_policy_id smallint DEFAULT 1 NOT NULL, + pai_rewrite_rule character varying, + pai_rewrite_result character varying, CONSTRAINT customers_auth_max_dst_number_length CHECK ((dst_number_min_length >= 0)), CONSTRAINT customers_auth_max_src_number_length CHECK ((src_number_max_length >= 0)), CONSTRAINT customers_auth_min_dst_number_length CHECK ((dst_number_min_length >= 0)), @@ -42435,7 +42521,7 @@ CREATE TABLE data_import.import_customers_auth ( uri_domain character varying, pop_name character varying, pop_id integer, - diversion_policy_id integer, + diversion_policy_id smallint, diversion_policy_name character varying, diversion_rewrite_result character varying, diversion_rewrite_rule character varying, @@ -42487,7 +42573,11 @@ CREATE TABLE data_import.import_customers_auth ( dst_number_field_name smallint, cps_limit double precision, privacy_mode_id smallint, - privacy_mode_name character varying + privacy_mode_name character varying, + pai_policy_id smallint, + pai_policy_name character varying, + pai_rewrite_rule character varying, + pai_rewrite_result character varying ); diff --git a/spec/factories/customers_auths.rb b/spec/factories/customers_auths.rb index 55d15717e..bbbf1d9fd 100644 --- a/spec/factories/customers_auths.rb +++ b/spec/factories/customers_auths.rb @@ -25,6 +25,8 @@ # interface :string default([]), not null, is an Array # ip :inet default(["\"127.0.0.0/8\""]), is an Array # name :string not null +# pai_rewrite_result :string +# pai_rewrite_rule :string # reject_calls :boolean default(FALSE), not null # require_incoming_auth :boolean default(FALSE), not null # send_billing_information :boolean default(FALSE), not null diff --git a/spec/factories/importing/customers_auths.rb b/spec/factories/importing/customers_auths.rb index d72b677c1..c71ae9ea0 100644 --- a/spec/factories/importing/customers_auths.rb +++ b/spec/factories/importing/customers_auths.rb @@ -35,6 +35,9 @@ # max_dst_number_length :integer(2) # min_dst_number_length :integer(2) # name :string +# pai_policy_name :string +# pai_rewrite_result :string +# pai_rewrite_rule :string # pop_name :string # privacy_mode_name :string # radius_accounting_profile_name :string @@ -66,13 +69,14 @@ # x_yeti_auth :string # account_id :integer(4) # customer_id :integer(4) -# diversion_policy_id :integer(4) +# diversion_policy_id :integer(2) # dst_number_field_id :integer(2) # dst_numberlist_id :integer(4) # dump_level_id :integer(4) # gateway_id :integer(4) # lua_script_id :integer(2) # o_id :bigint(8) +# pai_policy_id :integer(2) # pop_id :integer(4) # privacy_mode_id :integer(2) # radius_accounting_profile_id :integer(2) diff --git a/spec/models/customers_auth_normalized_spec.rb b/spec/models/customers_auth_normalized_spec.rb index 5b695a968..af2e83b91 100644 --- a/spec/models/customers_auth_normalized_spec.rb +++ b/spec/models/customers_auth_normalized_spec.rb @@ -25,6 +25,8 @@ # interface :string # ip :inet not null # name :string not null +# pai_rewrite_result :string +# pai_rewrite_rule :string # reject_calls :boolean default(FALSE), not null # require_incoming_auth :boolean default(FALSE), not null # send_billing_information :boolean default(FALSE), not null diff --git a/spec/models/customers_auth_spec.rb b/spec/models/customers_auth_spec.rb index 9af564d40..4f463fbc5 100644 --- a/spec/models/customers_auth_spec.rb +++ b/spec/models/customers_auth_spec.rb @@ -25,6 +25,8 @@ # interface :string default([]), not null, is an Array # ip :inet default(["\"127.0.0.0/8\""]), is an Array # name :string not null +# pai_rewrite_result :string +# pai_rewrite_rule :string # reject_calls :boolean default(FALSE), not null # require_incoming_auth :boolean default(FALSE), not null # send_billing_information :boolean default(FALSE), not null diff --git a/spec/sql/switch22/route_spec.rb b/spec/sql/switch22/route_spec.rb index 24c8f6767..583898773 100644 --- a/spec/sql/switch22/route_spec.rb +++ b/spec/sql/switch22/route_spec.rb @@ -100,23 +100,27 @@ def routing_sp let(:identity) { '[]' } let(:i_interface) { 'primary' } let(:x_yeti_auth) { nil } - let(:diversion) { '[ - {"h": "domain1", "n": null, "p": 5060, "s": "sip", "u": "user1", "np": {"nparam1": "nval1"}, "uh": {"uhdr1": "uhval1"}, "up": {"uparam1": "uval11", "uparam2": "uval12"}}, - {"h": "domain2", "n": "test2", "p": 5061, "s": "sip", "u": "user2", "up": {"uparam1": "uval21", "uparam2": "uval22"}}, - {"h": "domain3", "n": "test3", "p": 5062, "s": "sips", "u": "user3", "up": {"uparam1": "uval31", "uparam2": "uval32"}}, - {"s": "tel", "u": "1234567890"}]' } + let(:diversion) { + '[ + {"h": "domain1", "n": null, "p": 5060, "s": "sip", "u": "user1", "np_arr": ["nparam1:nval1"], "uh_arr": ["uhdr1:uhval1"], "up_arr": ["uparam1:uval11","uparam2:uval12"]}, + {"h": "domain2", "n": "test2", "p": 5061, "s": "sip", "u": "user2", "np_arr": ["nparam1:nval1"], "uh_arr": ["uhdr1:uhval1"], "up_arr": ["uparam1:uval11","uparam2:uval12"]}, + {"h": "domain3", "n": "test3", "p": 5062, "s": "sips", "u": "user3", "np_arr": ["nparam1:nval1"], "uh_arr": ["uhdr1:uhval1"], "up_arr": ["uparam1:uval11","uparam2:uval12"]}, + {"s": "tel", "u": "1234567890"}]' + } let(:x_orig_ip) { '3.3.3.3' } let(:x_orig_port) { 6050 } let(:x_orig_protocol_id) { 2 } - let(:pai) { '[ - {"h": "domain1", "n": null, "p": 5060, "s": "sip", "u": "user1", "np": {"nparam1": "nval1"}, "uh": {"uhdr1": "uhval1"}, "up": {"uparam1": "uval11", "uparam2": "uval12"}}, - {"h": "domain2", "n": "test2", "p": 5061, "s": "sip", "u": "user2", "up": {"uparam1": "uval21", "uparam2": "uval22"}}, - {"h": "domain3", "n": "test3", "p": 5062, "s": "sips", "u": "user3", "up": {"uparam1": "uval31", "uparam2": "uval32"}}, + let(:pai) { + '[ + {"h": "domain1", "n": null, "p": 5060, "s": "sip", "u": "user1", "np_arr": ["nparam1:nval1"], "uh_arr": ["uhdr1:uhval1"], "up_arr": ["uparam1:uval11","uparam2:uval12"]}, + {"h": "domain2", "n": "test2", "p": 5061, "s": "sip", "u": "user2", "np_arr": ["nparam1:nval1"], "uh_arr": ["uhdr1:uhval1"], "up_arr": ["uparam1:uval11","uparam2:uval12"]}, + {"h": "domain3", "n": "test3", "p": 5062, "s": "sips", "u": "user3", "np_arr": ["nparam1:nval1"], "uh_arr": ["uhdr1:uhval1"], "up_arr": ["uparam1:uval11","uparam2:uval12"]}, {"s": "tel", "u": "1234567890"} - ]' } - let(:ppi) { '{"h": "domain1", "n": null, "p": 5060, "s": "sip", "u": "user1", "np": {"nparam1": "nval1"}, "uh": {"uhdr1": "uhval1"}, "up": {"uparam1": "uval11", "uparam2": "uval12"}}' } + ]' + } + let(:ppi) { '{"h": "domain1", "n": null, "p": 5060, "s": "sip", "u": "user1", "np_arr": ["nparam1:nval1"], "uh_arr": ["uhdr1:uhval1"], "up_arr": ["uparam1:uval11","uparam2:uval12"]}' } let(:privacy) { 'none' } - let(:rpid) { '[ {"h": "domain1", "n": null, "p": 5060, "s": "sip", "u": "user1", "np": {"nparam1": "nval1"}, "uh": {"uhdr1": "uhval1"}, "up": {"uparam1": "uval11", "uparam2": "uval12"}}]'} + let(:rpid) { '[ {"h": "domain1", "n": null, "p": 5060, "s": "sip", "u": "user1", "np_arr": ["nparam1:nval1"], "uh_arr": ["uhdr1:uhval1"], "up_arr": ["uparam1:uval11","uparam2:uval12"]}]' } let(:rpid_privacy) { 'rpid-privacy' } shared_examples 'routing' do @@ -501,6 +505,7 @@ def routing_sp diversion_policy_id: customer_auth_diversion_policy_id, diversion_rewrite_rule: customer_auth_diversion_rewrite_rule, diversion_rewrite_result: customer_auth_diversion_rewrite_result, + pai_policy_id: customer_auth_pai_policy_id, cps_limit: customer_auth_cps_limit, src_numberlist_id: customer_auth_src_numberlist_id, dst_numberlist_id: customer_auth_dst_numberlist_id, @@ -524,9 +529,10 @@ def routing_sp let(:customer_auth_interface) { [] } let(:customer_auth_reject_calls) { false } let(:customer_auth_require_incoming_auth) { false } - let(:customer_auth_diversion_policy_id) { 1 } # do not accept diversion header + let(:customer_auth_diversion_policy_id) { CustomersAuth::DIVERSION_POLICY_NOT_ACCEPT } let(:customer_auth_diversion_rewrite_rule) { nil } # removing +380 let(:customer_auth_diversion_rewrite_result) { nil } + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_NOT_ACCEPT } let(:customer_auth_cps_limit) { nil } let(:customer_auth_src_numberlist_id) { nil } let(:customer_auth_dst_numberlist_id) { nil } @@ -1434,7 +1440,7 @@ def routing_sp context 'Authorized, CustomerAuth SRC numberlist, fallback to Diversion' do let(:customer_auth_src_numberlist_use_diversion) { true } - let(:customer_auth_diversion_policy_id) { 2 } # accept + let(:customer_auth_diversion_policy_id) { CustomersAuth::DIVERSION_POLICY_ACCEPT } let!(:nl) { create(:numberlist, mode_id: nl_mode, default_action_id: Routing::Numberlist::DEFAULT_ACTION_ACCEPT) @@ -1448,15 +1454,17 @@ def routing_sp let(:customer_auth_src_numberlist_id) { nl.id } let(:from_name) { '111111111' } ## not matching - let(:diversion) { '[ - {"s": "sip", "n": "name1", "u": "12345678", "h": "domain1", "p": 5060 }, - {"s": "sip", "n": "name2", "u": "111", "h": "domain2", "p": 5060 } - ]'} + let(:diversion) { + '[ + {"s": "sip", "n": "name1", "u": "12345678", "h": "domain1", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}, + {"s": "sip", "n": "name2", "u": "111", "h": "domain2", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]} + ]' + } context 'not matched in strict mode' do let(:nl_mode) { Routing::Numberlist::MODE_STRICT } let(:from_name) { '122' } - let(:diversion) { '[{"s": "sip", "n": "name1", "u": "100500", "h": "domain1", "p": 5060 }]'} + let(:diversion) { '[{"s": "sip", "n": "name1", "u": "100500", "h": "domain1", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}]' } it 'reject by dst numberlist' do expect(subject.size).to eq(2) @@ -2059,13 +2067,15 @@ def routing_sp end context 'Authorized, send_billing_information enabled, Diversion processing' do - let(:customer_auth_diversion_policy_id) { 2 } # Accept + let(:customer_auth_diversion_policy_id) { CustomersAuth::DIVERSION_POLICY_ACCEPT } let(:customer_auth_diversion_rewrite_rule) { '^\+380(.*)$' } # removing +380 let(:customer_auth_diversion_rewrite_result) { '\1' } - let(:diversion) { '[ - {"s": "sip", "n": "name1", "u": "+38067689798989", "h": "domain1", "p": 5060 }, - {"s": "sip", "n": "name2", "u": "+3800000000", "h": "domain2", "p": 5060 } - ]'} + let(:diversion) { + '[ + {"s": "sip", "n": "name1", "u": "+38067689798989", "h": "domain1", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}, + {"s": "sip", "n": "name2", "u": "+3800000000", "h": "domain2", "p": 5062, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]} + ]' + } let(:vendor_gw_term_append_headers_req) { '' } let(:vendor_gw_diversion_send_mode_id) { 2 } # send Diversion as SIP URI @@ -2075,22 +2085,24 @@ def routing_sp let!(:expected_headers) { [ - "Diversion: ", - "Diversion: " + "Diversion: \"name1\" ;nparam1=nval1", + "Diversion: \"name2\" ;nparam1=nval1" ] } context 'without append headers, SIP ' do let(:vendor_gw_term_append_headers_req) { '' } - let(:diversion) { '[ - {"s": "sip", "n": "name1", "u": "+38067689798989", "h": "domain1", "p": 5060 }, - {"s": "sip", "n": "name2", "u": "+3800000000", "h": "domain2", "p": 5060 } - ]'} + let(:diversion) { + '[ + {"s": "sip", "n": "name1", "u": "+38067689798989", "h": "domain1", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}, + {"s": "sip", "n": "name2", "u": "+3800000000", "h": "domain2", "p": 5062, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]} + ]' + } let!(:expected_headers) { [ - "Diversion: ", - "Diversion: " + "Diversion: \"name1\" ;nparam1=nval1", + "Diversion: \"name2\" ;nparam1=nval1" ] } @@ -2108,17 +2120,19 @@ def routing_sp context 'without append headers, TEL' do let(:vendor_gw_term_append_headers_req) { '' } - let(:diversion) { '[ - {"s": "sip", "n": "name1", "u": "+38067689798989", "h": "domain1", "p": 5060 }, - {"s": "sip", "n": "name2", "u": "+3800000001", "h": "domain2", "p": 5060 } - ]'} + let(:diversion) { + '[ + {"s": "sip", "n": "name1", "u": "+38067689798989", "h": "domain1", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}, + {"s": "sip", "n": "name2", "u": "+3800000001", "h": "domain2", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]} + ]' + } let(:vendor_gw_diversion_send_mode_id) { 3 } # send Diversion as TEL let!(:expected_headers) { [ - 'Diversion: ', - 'Diversion: ' + 'Diversion: ;nparam1=nval1', + 'Diversion: ;nparam1=nval1' ] } @@ -2139,7 +2153,7 @@ def routing_sp let(:diversion) { '[]' } let(:vendor_gw_diversion_send_mode_id) { 3 } # send Diversion as TEL - let!(:expected_headers) { [ ] } + let!(:expected_headers) { [] } it 'response ' do expect(subject.size).to eq(2) @@ -2155,15 +2169,17 @@ def routing_sp context 'with append headers' do let(:vendor_gw_term_append_headers_req) { 'Header5: value5\r\nHeader6: value7' } - let(:diversion) { '[ - {"s": "sip", "n": "name1", "u": "+38067689798989", "h": "domain1", "p": 5060 }, - {"s": "sip", "n": "name2", "u": "+3800000000", "h": "domain2", "p": 5060 } - ]'} + let(:diversion) { + '[ + {"s": "sip", "n": "name1", "u": "+38067689798989", "h": "domain1", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}, + {"s": "sip", "n": "name2", "u": "+3800000000", "h": "domain2", "p": 5062, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]} + ]' + } let!(:expected_headers) { [ - "Diversion: ", - "Diversion: ", + "Diversion: \"name1\" ;nparam1=nval1", + "Diversion: \"name2\" ;nparam1=nval1", 'Header5: value5', 'Header6: value7' ] @@ -2181,10 +2197,222 @@ def routing_sp end end - context 'Authorized, PAI send modes' do + context 'Authorized, PAI processing' do let(:from_name) { '123456789' } - context 'without append headers, SIP ' do + context 'Customer Auth PAI Policy, PAI present' do + # we testing there only PAI processing in customer auth. + # we will use trm gw pai_send_mode_relay SIP for tests + let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY_AS_SIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + + let(:pai) { + '[ + {"s": "sip", "n": "name1", "u": null, "h": "domain1", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}, + {"s": "sip", "n": "name2", "u": "", "h": "domain2", "p": 5062, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}, + {"s": "sip", "n": "name3", "u": "+3800000000", "h": "domain2", "p": 5062, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]} + ]' + } + + let(:ppi) { + '{"s": "sip", "n": "name1", "u": "+38067689798989", "h": "domain1", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}' + } + + context 'Not accepted' do + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_NOT_ACCEPT } + + let!(:expected_headers) { [] } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'Accepted' do + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } + + let!(:expected_headers) { + [ + 'P-Asserted-Identity: "name3" ;nparam1=nval1', + 'P-Preferred-Identity: "name1" ;nparam1=nval1' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'Required' do + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_REQUIRE } + + let!(:expected_headers) { + [ + 'P-Asserted-Identity: "name3" ;nparam1=nval1', + 'P-Preferred-Identity: "name1" ;nparam1=nval1' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + end + + context 'Customer Auth PAI Policy, PAI useless' do + # Useless pai has no user part or tel number + + # we testing there only PAI processing in customer auth. + # we will use trm gw pai_send_mode_relay SIP for tests + + let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY_AS_SIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + + let(:pai) { + '[ + {"s": "sip", "n": "name1", "u": null, "h": "domain1", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}, + {"s": "sip", "n": "name2", "u": "", "h": "domain2", "p": 5062, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}, + {"s": "tel", "n": null, "u": "", "h": null, "p": null, "np_arr": [], "uh_arr": [], "up_arr": []} + ]' + } + + let(:ppi) { + '{"s": "sip", "n": "name1", "u": null, "h": "domain1", "p": 5060, "np_arr": ["nparam1=nval1"], "uh_arr": ["uhdr1=uhval1"], "up_arr": ["uparam1=uval11","uparam2=uval12"]}' + } + + context 'Not accepted' do + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_NOT_ACCEPT } + + let!(:expected_headers) { [] } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'Accepted' do + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } + + let!(:expected_headers) { [] } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'Required' do + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_REQUIRE } + + it 'reject call' do + expect(subject.size).to eq(1) + expect(subject.first[:disconnect_code_id]).to eq(DisconnectCode::DC_PAI_REQUIRED) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:customer_acc_id]).to be + expect(subject.first[:dump_level_id]).to be + expect(subject.first[:dst_prefix_in]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(nil) + end + end + end + + context 'Customer Auth PAI Policy, PAI missing' do + # we testing there only PAI processing in customer auth. + # we will use trm gw pai_send_mode_relay SIP for tests + let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY_AS_SIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + + let(:pai) { '[]' } + let(:ppi) { nil } + + context 'Not accepted' do + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_NOT_ACCEPT } + + let!(:expected_headers) { [] } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'Accepted' do + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } + + let!(:expected_headers) { [] } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'Required' do + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_REQUIRE } + + let!(:expected_headers) { [] } + + it 'reject call' do + expect(subject.size).to eq(1) + expect(subject.first[:disconnect_code_id]).to eq(DisconnectCode::DC_PAI_REQUIRED) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:customer_acc_id]).to be + expect(subject.first[:dump_level_id]).to be + expect(subject.first[:dst_prefix_in]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(nil) + end + end + end + + context 'Term gw, SIP ' do let(:vendor_gw_term_append_headers_req) { '' } let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_BUILD_SIP } # sip URI let(:vendor_gw_pai_domain) { 'sip.pai.com' } @@ -2207,7 +2435,7 @@ def routing_sp end end - context 'without append headers, TEL' do + context 'Term gw append headers, TEL' do let(:vendor_gw_term_append_headers_req) { '' } let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_BUILD_TEL } # tel: URI @@ -2217,7 +2445,6 @@ def routing_sp ] } - it 'response with Diversion headers ' do expect(subject.size).to eq(2) expect(subject.first[:customer_auth_id]).to be @@ -2230,7 +2457,7 @@ def routing_sp end end - context 'without append headers, SIP with user=phone ' do + context 'Term gw append headers, SIP with user=phone ' do let(:vendor_gw_term_append_headers_req) { '' } let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_BUILD_SIP_WITH_USER_PHONE } # sip URI let(:vendor_gw_pai_domain) { 'sip.pai.com' } @@ -2253,8 +2480,9 @@ def routing_sp end end - context 'without append headers, RELAY NULL' do + context 'Term gw, RELAY when PAI missing' do let(:vendor_gw_term_append_headers_req) { '' } + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY } let(:vendor_gw_pai_domain) { 'sip.pai.com' } let(:pai) { '[]' } @@ -2421,15 +2649,18 @@ def routing_sp end end - context 'without append headers, RELAY' do + context 'Term gw, RELAY when PAI present' do let(:vendor_gw_term_append_headers_req) { '' } + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY } let(:vendor_gw_pai_domain) { 'sip.pai.com' } - let(:pai) { '[ + let(:pai) { + '[ {"s": "sip", "n": "p name1", "u": "pai-user", "h": "pai.domain.example.com", "p": null }, {"s": "sip", "n": "p name2", "u": "pai-user2", "h": "pai.domain.example.com", "p": null } - ]'} + ]' + } let(:ppi) { '{"s": "sip", "n": "pp name1", "u": "ppi-user", "h": "ppi.domain.example.com", "p": null }' } @@ -2459,10 +2690,12 @@ def routing_sp let(:vendor_gw_pai_domain) { 'sip.pai.com' } let(:privacy) { 'id' } - let(:pai) { '[ + let(:pai) { + '[ {"s": "sip", "n": "p name", "u": "pai-user", "h": "pai.domain.example.com", "p": null }, {"s": "sip", "n": "p name2", "u": "pai-user2", "h": "pai.domain.example.com", "p": null } - ]'} + ]' + } let(:ppi) { '{"s": "sip", "n": "pp name1", "u": "ppi-user", "h": "ppi.domain.example.com", "p": null }' } @@ -2495,10 +2728,12 @@ def routing_sp let(:vendor_gw_pai_domain) { 'sip.pai.com' } let(:privacy) { 'id' } - let(:pai) { '[ + let(:pai) { + '[ {"s": "sip", "n": "p name", "u": "pai-user", "h": "pai.domain.example.com", "p": null }, {"s": "sip", "n": "p name2", "u": "pai-user2", "h": "pai.domain.example.com", "p": null } - ]'} + ]' + } let(:ppi) { '{"s": "sip", "n": "pp name1", "u": "ppi-user", "h": "ppi.domain.example.com", "p": null }' } @@ -2519,10 +2754,12 @@ def routing_sp let(:vendor_gw_pai_domain) { 'sip.pai.com' } let(:privacy) { 'id' } - let(:pai) { '[ + let(:pai) { + '[ {"s": "sip", "n": "p name1", "u": "pai-user", "h": "pai.domain.example.com", "p": null }, {"s": "sip", "n": "p name2", "u": "pai-user2", "h": "pai.domain.example.com", "p": null } - ]'} + ]' + } let(:ppi) { '{"s": "sip", "n": "pp name1", "u": "ppi-user", "h": "ppi.domain.example.com", "p": null }' } @@ -2547,10 +2784,12 @@ def routing_sp let(:vendor_gw_pai_domain) { 'sip.pai.com' } let(:privacy) { 'id;critical' } - let(:pai) { '[ + let(:pai) { + '[ {"s": "sip", "n": "p name", "u": "pai-user", "h": "pai.domain.example.com", "p": null }, {"s": "sip", "n": "p name2", "u": "pai-user2", "h": "pai.domain.example.com", "p": null } - ]'} + ]' + } let(:ppi) { '{"s": "sip", "n": "pp name1", "u": "ppi-user", "h": "ppi.domain.example.com", "p": null }' } @@ -2571,14 +2810,15 @@ def routing_sp let(:vendor_gw_pai_domain) { 'sip.pai.com' } let(:privacy) { 'id' } - let(:pai) { '[ + let(:pai) { + '[ {"s": "sip", "n": "p name", "u": "pai-user", "h": "pai.domain.example.com", "p": null }, {"s": "sip", "n": "p name2", "u": "pai-user2", "h": "pai.domain.example.com", "p": null } - ]'} + ]' + } let(:ppi) { '{"s": "sip", "n": "pp name1", "u": "ppi-user", "h": "ppi.domain.example.com", "p": null }' } - it 'response without PAI headers ' do expect(subject.size).to eq(2) expect(subject.first[:customer_auth_id]).to be @@ -2600,10 +2840,12 @@ def routing_sp let(:vendor_gw_pai_domain) { 'sip.pai.com' } let(:privacy) { 'id' } - let(:pai) { '[ + let(:pai) { + '[ {"s": "sip", "n": "p name", "u": "pai-user", "h": "pai.domain.example.com", "p": null }, {"s": "sip", "n": "p name2", "u": "pai-user2", "h": "pai.domain.example.com", "p": null } - ]'} + ]' + } let(:ppi) { '{"s": "sip", "n": "pp name1", "u": "ppi-user", "h": "ppi.domain.example.com", "p": null }' } @@ -2631,6 +2873,907 @@ def routing_sp end end + context 'Term gw, RELAY, RELAY as TEL when PAI present' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } + let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY_AS_TEL } + + let(:pai) { + '[ + {"s": "sip", "n": "p name1", "u": "", "h": "pai.domain.example.com", "p": null }, + {"s": "sip", "n": "p name1", "u": "pai-user", "h": "pai.domain.example.com", "p": null }, + {"s": "sip", "n": "p name2", "u": "pai-user2", "h": "pai.domain.example.com", "p": null }, + {"s": "tel", "u": "tel-user2" } + ]' + } + + let(:ppi) { '{"s": "sip", "n": "pp name1", "u": "ppi-user", "h": "ppi.domain.example.com", "p": null }' } + + let!(:expected_headers) { + [ + 'P-Asserted-Identity: ', + 'P-Asserted-Identity: ', + 'P-Asserted-Identity: ', + 'P-Preferred-Identity: ' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + + context 'with privacy id and disabled privacy policy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_DISABLE } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:ruri]).to be + expect(subject.first[:from]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id; critical and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id;critical' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and apply privacy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_APPLY } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response without PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('Anonymous') # Original destination + expect(subject.first[:src_prefix_out]).to eq('anonymous') # Original destination + expect(subject.first[:from]).to eq('"Anonymous" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq("Privacy: #{privacy}") + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and trusted gw' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_TRUSTED } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + let!(:expected_headers) { + [ + 'Privacy: id', + 'P-Asserted-Identity: ', + 'P-Asserted-Identity: ', + 'P-Asserted-Identity: ', + 'P-Preferred-Identity: ' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + end + + context 'Term gw, RELAY, RELAY as TEL when PAI missing' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } + let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY_AS_TEL } + + let(:pai) { '[]' } + let(:ppi) { nil } + + let!(:expected_headers) { [] } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + + context 'with privacy id and disabled privacy policy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_DISABLE } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:ruri]).to be + expect(subject.first[:from]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id; critical and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id;critical' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and apply privacy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_APPLY } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response without PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('Anonymous') # Original destination + expect(subject.first[:src_prefix_out]).to eq('anonymous') # Original destination + expect(subject.first[:from]).to eq('"Anonymous" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq("Privacy: #{privacy}") + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and trusted gw' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_TRUSTED } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + let!(:expected_headers) { + [ + 'Privacy: id' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + end + + context 'Term gw, RELAY, RELAY as SIP when PAI present' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } + let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY_AS_SIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + + let(:pai) { + '[ + {"s": "sip", "n": "p name1", "u": "", "h": "pai.domain.example.com", "p": null }, + {"s": "sip", "n": "p name1", "u": "pai-user", "h": "pai.domain.example.com", "p": null }, + {"s": "sip", "n": "p name2", "u": "pai-user2", "h": "pai.domain.example.com", "p": null }, + {"s": "tel", "u": "tel-user2" } + ]' + } + + let(:ppi) { '{"s": "sip", "n": "pp name1", "u": "ppi-user", "h": "ppi.domain.example.com", "p": null }' } + + let!(:expected_headers) { + [ + 'P-Asserted-Identity: "p name1" ', + 'P-Asserted-Identity: "p name2" ', + 'P-Asserted-Identity: ', + 'P-Preferred-Identity: "pp name1" ' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + + context 'with privacy id and disabled privacy policy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_DISABLE } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:ruri]).to be + expect(subject.first[:from]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id; critical and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id;critical' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and apply privacy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_APPLY } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response without PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('Anonymous') # Original destination + expect(subject.first[:src_prefix_out]).to eq('anonymous') # Original destination + expect(subject.first[:from]).to eq('"Anonymous" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq("Privacy: #{privacy}") + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and trusted gw' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_TRUSTED } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + let!(:expected_headers) { + [ + 'Privacy: id', + 'P-Asserted-Identity: "p name1" ', + 'P-Asserted-Identity: "p name2" ', + 'P-Asserted-Identity: ', + 'P-Preferred-Identity: "pp name1" ' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + end + + context 'Term gw, RELAY, RELAY as SIP when PAI missing' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } + let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY_AS_SIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + + let(:pai) { '[]' } + let(:ppi) { nil } + + let!(:expected_headers) { [] } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + + context 'with privacy id and disabled privacy policy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_DISABLE } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:ruri]).to be + expect(subject.first[:from]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id; critical and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id;critical' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and apply privacy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_APPLY } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response without PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('Anonymous') # Original destination + expect(subject.first[:src_prefix_out]).to eq('anonymous') # Original destination + expect(subject.first[:from]).to eq('"Anonymous" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq("Privacy: #{privacy}") + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and trusted gw' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_TRUSTED } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + let!(:expected_headers) { + [ + 'Privacy: id' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + end + + context 'Term gw, RELAY, RELAY as SIP replace domain when PAI present' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } + let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY_AS_SIP_FORCE_DOMAIN } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + + let(:pai) { + '[ + {"s": "sip", "n": "p name1", "u": "", "h": "pai.domain.example.com", "p": null }, + {"s": "sip", "n": "p name1", "u": "pai-user", "h": "pai.domain.example.com", "p": null }, + {"s": "sip", "n": "p name2", "u": "pai-user2", "h": "pai.domain.example.com", "p": null }, + {"s": "tel", "u": "tel-user2" } + ]' + } + + let(:ppi) { '{"s": "sip", "n": "pp name1", "u": "ppi-user", "h": "ppi.domain.example.com", "p": null }' } + + let!(:expected_headers) { + [ + 'P-Asserted-Identity: "p name1" ', + 'P-Asserted-Identity: "p name2" ', + 'P-Asserted-Identity: ', + 'P-Preferred-Identity: "pp name1" ' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + + context 'with privacy id and disabled privacy policy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_DISABLE } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:ruri]).to be + expect(subject.first[:from]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id; critical and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id;critical' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and apply privacy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_APPLY } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response without PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('Anonymous') # Original destination + expect(subject.first[:src_prefix_out]).to eq('anonymous') # Original destination + expect(subject.first[:from]).to eq('"Anonymous" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq("Privacy: #{privacy}") + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and trusted gw' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_TRUSTED } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + let!(:expected_headers) { + [ + 'Privacy: id', + 'P-Asserted-Identity: "p name1" ', + 'P-Asserted-Identity: "p name2" ', + 'P-Asserted-Identity: ', + 'P-Preferred-Identity: "pp name1" ' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + end + + context 'Term gw, RELAY, RELAY as SIP replace domain when PAI missing' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:customer_auth_pai_policy_id) { CustomersAuth::PAI_POLICY_ACCEPT } + let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_RELAY_AS_SIP_FORCE_DOMAIN } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + + let(:pai) { '[]' } + let(:ppi) { nil } + + let!(:expected_headers) { [] } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + + context 'with privacy id and disabled privacy policy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_DISABLE } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:ruri]).to be + expect(subject.first[:from]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:dst_prefix_out]).to eq('uri-name') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id; critical and SKIP GW critical' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_SKIP_CRITICAL } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id;critical' } + + it 'response with skipped route' do + expect(subject.size).to eq(2) + expect(subject.first[:ruri]).to eq(nil) + expect(subject.first[:from]).to eq(nil) + expect(subject.first[:dst_prefix_routing]).to eq(nil) + expect(subject.first[:append_headers_req]).to eq(nil) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and apply privacy' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_APPLY } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + it 'response without PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('Anonymous') # Original destination + expect(subject.first[:src_prefix_out]).to eq('anonymous') # Original destination + expect(subject.first[:from]).to eq('"Anonymous" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq("Privacy: #{privacy}") + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + + context 'with privacy id and trusted gw' do + let(:vendor_gw_term_append_headers_req) { '' } + let(:vendor_gw_privacy_mode_id) { Gateway::PRIVACY_MODE_TRUSTED } + let(:vendor_gw_pai_domain) { 'sip.pai.com' } + let(:privacy) { 'id' } + + let!(:expected_headers) { + [ + 'Privacy: id' + ] + } + + it 'response with PAI headers ' do + expect(subject.size).to eq(2) + expect(subject.first[:customer_auth_id]).to be + expect(subject.first[:customer_id]).to be + expect(subject.first[:disconnect_code_id]).to eq(nil) # no routing Error + expect(subject.first[:src_name_out]).to eq('from display name') # Original destination + expect(subject.first[:src_prefix_out]).to eq('123456789') # Original destination + expect(subject.first[:from]).to eq('"from display name" ') # Original destination + expect(subject.first[:dst_prefix_routing]).to eq('uri-name') # Original destination + expect(subject.first[:append_headers_req]).to eq(expected_headers.join('\r\n')) + expect(subject.second[:disconnect_code_id]).to eq(113) # last profile with route not found error + end + end + end + context 'with append headers' do let(:vendor_gw_term_append_headers_req) { 'Header5: value5\r\nHeader6: value7' } let(:vendor_gw_pai_send_mode_id) { Gateway::PAI_SEND_MODE_BUILD_SIP } # sip: URI