From ce8bc30492d09e219abd5cb34dd2c0030750bc40 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Thu, 16 Feb 2017 13:16:08 +0100 Subject: [PATCH] TT#2386 sca: improvements * [to|from]_avp module parameters * sca_call_info_update() fallback if no Contact header is present * implement unsubscribe for call-info * use rr is_direction() to select tag for search * fix core on RPC command release_appearance * fix on-hold detection when direction is upstream Change-Id: I29c71374da6ae918b82a32987e5d9a52a252e478 --- debian/patches/series | 8 + .../sipwise/sca-call-info-unsubscribe.patch | 76 +++ debian/patches/sipwise/sca-debug.patch | 222 +++++++ .../sipwise/sca-fallback-if-no-contact.patch | 38 ++ ...n-release_appearance-RPC-command-par.patch | 38 ++ ...on-hold-detection-when-upstream-flow.patch | 36 + .../sca-fix-pickup-when-upstream-flow.patch | 120 ++++ debian/patches/sipwise/sca-line-seize.patch | 629 ++++++++++++++++++ .../patches/sipwise/sca-rr-is-direction.patch | 183 +++++ 9 files changed, 1350 insertions(+) create mode 100644 debian/patches/sipwise/sca-call-info-unsubscribe.patch create mode 100644 debian/patches/sipwise/sca-debug.patch create mode 100644 debian/patches/sipwise/sca-fallback-if-no-contact.patch create mode 100644 debian/patches/sipwise/sca-fix-core-when-release_appearance-RPC-command-par.patch create mode 100644 debian/patches/sipwise/sca-fix-on-hold-detection-when-upstream-flow.patch create mode 100644 debian/patches/sipwise/sca-fix-pickup-when-upstream-flow.patch create mode 100644 debian/patches/sipwise/sca-line-seize.patch create mode 100644 debian/patches/sipwise/sca-rr-is-direction.patch diff --git a/debian/patches/series b/debian/patches/series index d7d8777a8..978f0e8ea 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -53,6 +53,14 @@ sipwise/utils-kamctl-refresh-dbschema.patch sipwise/sca-use-To-header-if-in-dialog-as-target.patch sipwise/sca-fix-sca_call_info_update-params.patch sipwise/sca-use-onhold_bflag-value-only-when-set.patch +sipwise/sca-line-seize.patch +sipwise/sca-fallback-if-no-contact.patch +sipwise/sca-call-info-unsubscribe.patch +sipwise/sca-rr-is-direction.patch +sipwise/sca-fix-core-when-release_appearance-RPC-command-par.patch +sipwise/sca-fix-pickup-when-upstream-flow.patch +sipwise/sca-fix-on-hold-detection-when-upstream-flow.patch +sipwise/sca-debug.patch ## sipwise/tm-deep-cloning-of-the-request-for-fake-environment.patch sipwise/core-parser-reset_path_vector-remove-check-for-msg-m.patch diff --git a/debian/patches/sipwise/sca-call-info-unsubscribe.patch b/debian/patches/sipwise/sca-call-info-unsubscribe.patch new file mode 100644 index 000000000..5d082780e --- /dev/null +++ b/debian/patches/sipwise/sca-call-info-unsubscribe.patch @@ -0,0 +1,76 @@ +From: Victor Seva +Date: Thu, 13 Apr 2017 13:04:27 +0200 +Subject: sca: implement subscribe deletion with expires=0 for call-info + +Change-Id: I8cb4bb0db057f5f5754c5148a291029aaf30082d +--- + modules/sca/sca_subscribe.c | 27 ++++++++++++++++++++++++--- + 1 file changed, 24 insertions(+), 3 deletions(-) + +diff --git a/modules/sca/sca_subscribe.c b/modules/sca/sca_subscribe.c +index 3b92162..0022420 100644 +--- a/modules/sca/sca_subscribe.c ++++ b/modules/sca/sca_subscribe.c +@@ -1180,6 +1180,8 @@ sca_handle_subscribe( sip_msg_t *msg, str *uri_to, str *uri_from ) + int released = 0; + int_str val; + struct to_body *tmp_to; ++ sca_hash_slot *slot = NULL; ++ sca_hash_entry *ent = NULL; + + if ( parse_headers( msg, HDR_EOH_F, 0 ) < 0 ) { + LM_ERR( "header parsing failed: bad request" ); +@@ -1265,13 +1267,17 @@ sca_handle_subscribe( sip_msg_t *msg, str *uri_to, str *uri_from ) + goto done; + } + } +- ++ slot = sca_hash_table_slot_for_index( sca->subscriptions, idx ); + sca_hash_table_lock_index( sca->subscriptions, idx ); + +- sub = sca_hash_table_index_kv_find_unsafe( sca->subscriptions, idx, +- &req_sub.subscriber ); ++ ent = sca_hash_table_slot_kv_find_entry_unsafe( slot, &req_sub.subscriber ); ++ if (ent!=NULL) { ++ sub = (sca_subscription *)ent->value; ++ } + + if ( sub != NULL ) { ++ LM_DBG("sca_handle_subscribe: subscription[%.*s] found\n", ++ STR_FMT(&req_sub.subscriber)); + /* this will remove the subscription if expires == 0 */ + if ( sca_subscription_update_unsafe( sca, sub, &req_sub, idx ) < 0 ) { + SCA_SUB_REPLY_ERROR( sca, 500, "Internal Server Error - " +@@ -1323,10 +1329,24 @@ sca_handle_subscribe( sip_msg_t *msg, str *uri_to, str *uri_from ) + LM_INFO( "sca_handle_subscribe: released %d appearances " + "for subscriber %.*s", released, + STR_FMT( &req_sub.subscriber )); ++ } else { ++ LM_DBG("sca_handle_subscribe: subscriber[%.*s] doesn't " ++ "own any active appearances using target[%.*s]\n", ++ STR_FMT(&req_sub.subscriber), ++ STR_FMT(&req_sub.target_aor)); + } + } ++ if( req_sub.expires == 0 ) { ++ ent = sca_hash_table_slot_unlink_entry_unsafe( slot, ent ); ++ sub->expires = 0; ++ sub->dialog.notify_cseq += 1; ++ sub->state = SCA_SUBSCRIPTION_STATE_TERMINATED; ++ if(ent) sca_hash_entry_free( ent ); ++ } + } + } else { ++ LM_DBG("sca_handle_subscribe: subscription[%.*s] not found\n", ++ STR_FMT(&req_sub.subscriber)); + /* in-dialog request, but we didn't find it. */ + if ( !SCA_STR_EMPTY( to_tag )) { + SCA_SUB_REPLY_ERROR( sca, 481, +@@ -1362,6 +1382,7 @@ sca_handle_subscribe( sip_msg_t *msg, str *uri_to, str *uri_from ) + * but the dialog wasn't in our table. just reply with the + * subscription info we got, without saving or creating anything. + */ ++ LM_DBG("sca_handle_subscribe: expires=0 in-dialog but dialog not found\n"); + sub = &req_sub; + } + } diff --git a/debian/patches/sipwise/sca-debug.patch b/debian/patches/sipwise/sca-debug.patch new file mode 100644 index 000000000..bf00c7935 --- /dev/null +++ b/debian/patches/sipwise/sca-debug.patch @@ -0,0 +1,222 @@ +From: Victor Seva +Date: Tue, 18 Apr 2017 08:52:38 +0200 +Subject: sca: debug output + +Change-Id: Ib51bb44728ad9705e4e0fcc90e5d0e1873cb30d3 +--- + modules/sca/sca_appearance.c | 6 ++++++ + modules/sca/sca_call_info.c | 46 +++++++++++++++++++++++++++++++++++++++++--- + modules/sca/sca_dialog.c | 10 ++++++++++ + 3 files changed, 59 insertions(+), 3 deletions(-) + +diff --git a/modules/sca/sca_appearance.c b/modules/sca/sca_appearance.c +index e0ba91e..a0585bc 100644 +--- a/modules/sca/sca_appearance.c ++++ b/modules/sca/sca_appearance.c +@@ -1212,7 +1212,12 @@ sca_appearance_for_dialog_unsafe( sca_mod *scam, str *aor, sca_dialog *dialog, + return( NULL ); + } + ++ LM_DBG("search for call_id[%.*s] from_tag[%.*s]\n", ++ STR_FMT(&dialog->call_id), STR_FMT(&dialog->from_tag)); + for ( app = app_list->appearances; app != NULL; app = app->next ) { ++ LM_DBG("app.call_id[%.*s] app.from_tag[%.*s] app.to_tag[%.*s]\n", ++ STR_FMT(&app->dialog.call_id), STR_FMT(&app->dialog.from_tag), ++ STR_FMT(&app->dialog.to_tag)); + if ( SCA_STR_EQ( &app->dialog.call_id, &dialog->call_id ) && + SCA_STR_EQ( &app->dialog.from_tag, &dialog->from_tag )) { + #ifdef notdef +@@ -1222,6 +1227,7 @@ sca_appearance_for_dialog_unsafe( sca_mod *scam, str *aor, sca_dialog *dialog, + continue; + } + #endif /* notdef */ ++ LM_DBG("%.*s appearance-index %d found\n", STR_FMT(aor), app->index); + break; + } + } +diff --git a/modules/sca/sca_call_info.c b/modules/sca/sca_call_info.c +index 9ed63fd..0504ba6 100644 +--- a/modules/sca/sca_call_info.c ++++ b/modules/sca/sca_call_info.c +@@ -1002,6 +1002,7 @@ sca_call_info_invite_request_handler( sip_msg_t *msg, sca_call_info *call_info, + + if ( !upstream && !SCA_CALL_INFO_IS_SHARED_CALLER( call_info )) { + /* caller isn't SCA, no more to do. update callee in reply handler. */ ++ LM_DBG("caller isn't SCA, no more to do. update callee in reply handler\n"); + rc = 1; + goto done; + } +@@ -1019,6 +1020,7 @@ sca_call_info_invite_request_handler( sip_msg_t *msg, sca_call_info *call_info, + } + + if ( sca_call_is_held( msg )) { ++ LM_DBG("call_is_held\n"); + state = SCA_APPEARANCE_STATE_HELD; + if ( call_info->state == SCA_APPEARANCE_STATE_HELD_PRIVATE ) { + state = SCA_APPEARANCE_STATE_HELD_PRIVATE; +@@ -1027,14 +1029,18 @@ sca_call_info_invite_request_handler( sip_msg_t *msg, sca_call_info *call_info, + } + } else if ( !SCA_STR_EMPTY( &to->tag_value )) { + /* this is a reINVITE from an SCA line that put the call on hold */ ++ LM_DBG("reINVITE from an SCA line that put the call on hold\n"); + state = SCA_APPEARANCE_STATE_ACTIVE; + } else if ( sca_call_info_is_line_seize_reinvite( msg, call_info, + from, to, from_aor, to_aor )) { ++ LM_DBG("line_seize_reinvite\n"); + rc = sca_call_info_seize_held_call( msg, call_info, from, to, + from_aor, to_aor, contact_uri ); + if ( rc <= 0 ) { + goto done; + } ++ } else { ++ LM_DBG("Initial INVITE\n"); + } + /* otherwise, this is an initial INVITE */ + +@@ -1236,11 +1242,19 @@ sca_call_info_invite_reply_200_handler( sip_msg_t *msg, + int rc = -1; + + if ( SCA_CALL_INFO_IS_SHARED_CALLEE( call_info )) { ++ LM_DBG("SCA_CALL_INFO_IS_SHARED_CALLEE\n"); ++ if(sca->rr_api->is_direction(msg, RR_FLOW_DOWNSTREAM)==0) { ++ LM_DBG("downstream detected\n"); ++ } ++ if(sca->rr_api->is_direction(msg, RR_FLOW_UPSTREAM)==0) { ++ LM_DBG("upstream detected\n"); ++ } + rc = sca_call_info_uri_update( to_aor, call_info, from, to, + contact_uri, &msg->callid->body ); + } + + if ( !SCA_CALL_INFO_IS_SHARED_CALLER( call_info )) { ++ LM_DBG("NOT SCA_CALL_INFO_IS_SHARED_CALLER\n"); + goto done; + } + +@@ -1269,6 +1283,8 @@ sca_call_info_invite_reply_200_handler( sip_msg_t *msg, + &msg->callid->body, &from->tag_value, NULL, slot_idx ); + if ( app == NULL ) { + /* no SCA line is involved with this call */ ++ LM_DBG("no SCA line is involved with this call[%.*s]\n", ++ STR_FMT(from_aor)); + rc = 1; + goto done; + } +@@ -1433,6 +1449,8 @@ sca_call_info_ack_from_handler( sip_msg_t *msg, str *from_aor, str *to_aor ) + + /* can't send NOTIFYs until we unlock the slot below */ + } ++ } else { ++ LM_DBG("from_aor[%.*s] not shared appearance\n", STR_FMT(from_aor)); + } + + done: +@@ -1586,7 +1604,11 @@ sca_call_info_bye_handler( sip_msg_t *msg, sca_call_info *call_info, + str *tag = NULL; + + if ( msg->first_line.type == SIP_REQUEST ) { ++ LM_DBG("SIP_REQUEST\n"); + if ( SCA_CALL_INFO_IS_SHARED_CALLER( call_info )) { ++ LM_DBG("SCA_CALL_INFO_IS_SHARED_CALLER " ++ "from_aor[%.*s] to_aor[%.*s]\n", ++ STR_FMT(from_aor), STR_FMT(to_aor)); + slot_idx = sca_uri_lock_shared_appearance( sca, from_aor ); + if ( slot_idx < 0 ) { + LM_ERR( "sca_call_info_bye_handler: failed to acquire " +@@ -1640,7 +1662,11 @@ sca_call_info_bye_handler( sip_msg_t *msg, sca_call_info *call_info, + goto done; + } + } +- } ++ } else { ++ LM_DBG("NOT SCA_CALL_INFO_IS_SHARED_CALLER " ++ "from_aor[%.*s] to_aor[%.*s]\n", ++ STR_FMT(from_aor), STR_FMT(to_aor)); ++ } + + if ( slot_idx >= 0 ) { + sca_hash_table_unlock_index( sca->appearances, slot_idx ); +@@ -1695,6 +1721,7 @@ sca_call_info_bye_handler( sip_msg_t *msg, sca_call_info *call_info, + } + } + } else { ++ LM_DBG("SIP_REPLY\n"); + /* this is just a backup to catch anything missed on the BYE request */ + if ( SCA_CALL_INFO_IS_SHARED_CALLEE( call_info )) { + slot_idx = sca_hash_table_index_for_key( sca->appearances, to_aor ); +@@ -2079,29 +2106,42 @@ sca_call_info_update( sip_msg_t *msg, char *p1, str *uri_to, str *uri_from ) + if ( sca_uri_is_shared_appearance( sca, &from_aor )) { + if (( update_mask & SCA_CALL_INFO_SHARED_CALLER )) { + call_info.ua_shared |= SCA_CALL_INFO_SHARED_CALLER; ++ LM_DBG("SCA_CALL_INFO_SHARED_CALLER[%.*s]\n", ++ STR_FMT(&from_aor)); + } + } + if ( sca_uri_is_shared_appearance( sca, &to_aor )) { + if (( update_mask & SCA_CALL_INFO_SHARED_CALLEE )) { + call_info.ua_shared |= SCA_CALL_INFO_SHARED_CALLEE; ++ LM_DBG("SCA_CALL_INFO_SHARED_CALLEE[%.*s]\n", ++ STR_FMT(&to_aor)); + } + } + + if ( call_info_hdr == NULL ) { ++ LM_DBG("call_info_hdr is NULL\n"); + if ( SCA_CALL_INFO_IS_SHARED_CALLER( &call_info ) && + msg->first_line.type == SIP_REQUEST ) { ++ LM_DBG("SCA_CALL_INFO_IS_SHARED_CALLER && SIP_REQUEST\n"); + if ( !sca_subscription_aor_has_subscribers( + SCA_EVENT_TYPE_CALL_INFO, &from_aor )) { + call_info.ua_shared &= ~SCA_CALL_INFO_SHARED_CALLER; + sca_appearance_unregister( sca, &from_aor ); +- } ++ } else { ++ LM_DBG("from_aor[%.*s] has subscribers\n", ++ STR_FMT(&from_aor)); ++ } + } else if ( SCA_CALL_INFO_IS_SHARED_CALLEE( &call_info ) && + msg->first_line.type == SIP_REPLY ) { ++ LM_DBG("SCA_CALL_INFO_IS_SHARED_CALLEE && SIP_REPLY\n"); + if ( !sca_subscription_aor_has_subscribers( + SCA_EVENT_TYPE_CALL_INFO, &to_aor )) { + call_info.ua_shared &= ~SCA_CALL_INFO_SHARED_CALLEE; + sca_appearance_unregister( sca, &to_aor ); +- } ++ } else { ++ LM_DBG("to_aor[%.*s] has subscribers\n", ++ STR_FMT(&from_aor)); ++ } + } + } + +diff --git a/modules/sca/sca_dialog.c b/modules/sca/sca_dialog.c +index 9faf9e7..f31ae67 100644 +--- a/modules/sca/sca_dialog.c ++++ b/modules/sca/sca_dialog.c +@@ -43,6 +43,9 @@ sca_dialog_build_from_tags( sca_dialog *dialog, int maxlen, str *call_id, + return( -1 ); + } + ++ LM_DBG("call-id:%.*s from_tag:%.*s to_tag:%.*s\n", ++ STR_FMT(call_id), STR_FMT(from_tag), STR_FMT(to_tag)); ++ + memcpy( dialog->id.s, call_id->s, call_id->len ); + dialog->call_id.s = dialog->id.s; + dialog->call_id.len = call_id->len; +@@ -56,9 +59,16 @@ sca_dialog_build_from_tags( sca_dialog *dialog, int maxlen, str *call_id, + to_tag->s, to_tag->len ); + dialog->to_tag.s = dialog->id.s + call_id->len + from_tag->len; + dialog->to_tag.len = to_tag->len; ++ } else { ++ dialog->to_tag.s = NULL; ++ dialog->to_tag.len = 0; + } + dialog->id.len = len; + ++ LM_DBG("id:%.*s call-id:%.*s from_tag:%.*s to_tag:%.*s\n", ++ STR_FMT(&dialog->id), STR_FMT(&dialog->call_id), ++ STR_FMT(&dialog->from_tag), STR_FMT(&dialog->to_tag)); ++ + return( len ); + } + diff --git a/debian/patches/sipwise/sca-fallback-if-no-contact.patch b/debian/patches/sipwise/sca-fallback-if-no-contact.patch new file mode 100644 index 000000000..aa0dacb6d --- /dev/null +++ b/debian/patches/sipwise/sca-fallback-if-no-contact.patch @@ -0,0 +1,38 @@ +From: Victor Seva +Date: Thu, 30 Mar 2017 10:16:00 +0200 +Subject: sca: sca_call_info_update() fallback to default owner if no Contact + header is present + +Change-Id: I6a3f5b4c6786bf804bd10987863edf954e41f69b +--- + modules/sca/sca_call_info.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/modules/sca/sca_call_info.c b/modules/sca/sca_call_info.c +index 734fbe2..5592a68 100644 +--- a/modules/sca/sca_call_info.c ++++ b/modules/sca/sca_call_info.c +@@ -1976,9 +1976,6 @@ sca_call_info_update( sip_msg_t *msg, char *p1, str *uri_to, str *uri_from ) + rc = -1; + goto done; + } +- } else if ( rc < 0 ) { +- LM_ERR( "Bad Contact" ); +- goto done; + } + /* reset rc to -1 so we don't end up returning 0 to the script */ + rc = -1; +@@ -2025,6 +2022,13 @@ sca_call_info_update( sip_msg_t *msg, char *p1, str *uri_to, str *uri_from ) + LM_DBG("to_aor[%.*s] from_aor[%.*s]\n", + STR_FMT(&to_aor), STR_FMT(&from_aor)); + ++ if(contact_uri.s==NULL) { ++ contact_uri.s = "sip:127.0.0.1:5085;transport=udp"; ++ contact_uri.len = strlen(contact_uri.s); ++ LM_DBG("No Contact header, using default owner[%.*s]\n", ++ STR_FMT(&contact_uri)); ++ } ++ + /* early check to see if we're dealing with any SCA endpoints */ + if ( sca_uri_is_shared_appearance( sca, &from_aor )) { + if (( update_mask & SCA_CALL_INFO_SHARED_CALLER )) { diff --git a/debian/patches/sipwise/sca-fix-core-when-release_appearance-RPC-command-par.patch b/debian/patches/sipwise/sca-fix-core-when-release_appearance-RPC-command-par.patch new file mode 100644 index 000000000..bfca9b36e --- /dev/null +++ b/debian/patches/sipwise/sca-fix-core-when-release_appearance-RPC-command-par.patch @@ -0,0 +1,38 @@ +From: Victor Seva +Date: Thu, 8 Jun 2017 12:34:15 +0200 +Subject: sca: fix core when release_appearance RPC command parameter has + wrong index +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +> #0 0x00007fd8bba5a067 in raise () from /lib/x86_64-linux-gnu/libc.so.6 +> #1 0x00007fd8bba5b448 in abort () from /lib/x86_64-linux-gnu/libc.so.6 +> #2 0x00007fd8bba53266 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 +> #3 0x00007fd8bba53312 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6 +> #4 0x00007fd8a4b16328 in sca_appearance_list_unlink_index (app_list=0x7fd8a603c528, idx=0) at sca_appearance.c:254 +> #5 0x00007fd8a4ae0372 in sca_rpc_release_appearance (rpc=0x7fd8b1162300 , ctx=0x7ffc2ce9eef0) at sca_rpc.c:504 +> #6 0x00007fd8b0f38abb in process_rpc_req (buf=0x1e5e744 "\241\003\067oZ\274Ƒ\027sca.release_appearance", size=12344, bytes_needed=0x7ffc2ce9effc, sh=0xfefefefefefefe00, +> saved_state=0xfefefefefefefe00) at binrpc_run.c:675 + +Change-Id: Ied94a9872fa41ee5d6432380c549076da2fd6239 +--- + modules/sca/sca_rpc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/modules/sca/sca_rpc.c b/modules/sca/sca_rpc.c +index 5e6873b..cac8465 100644 +--- a/modules/sca/sca_rpc.c ++++ b/modules/sca/sca_rpc.c +@@ -482,6 +482,11 @@ sca_rpc_release_appearance( rpc_t *rpc, void *ctx ) + return; + } + ++ if (app_idx <= 0) { ++ rpc->fault(ctx, 500, "appearance-index must be > 0"); ++ return; ++ } ++ + if (( ht = sca->appearances ) == NULL ) { + rpc->fault( ctx, 500, "No active appearances" ); + return; diff --git a/debian/patches/sipwise/sca-fix-on-hold-detection-when-upstream-flow.patch b/debian/patches/sipwise/sca-fix-on-hold-detection-when-upstream-flow.patch new file mode 100644 index 000000000..fc8bd7313 --- /dev/null +++ b/debian/patches/sipwise/sca-fix-on-hold-detection-when-upstream-flow.patch @@ -0,0 +1,36 @@ +From: Victor Seva +Date: Fri, 9 Jun 2017 13:54:04 +0200 +Subject: sca: fix on-hold detection when upstream flow + +Change-Id: I0c7186c0e749b47254e4b34468b044286a413876 +--- + modules/sca/sca_call_info.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/modules/sca/sca_call_info.c b/modules/sca/sca_call_info.c +index 370fcc2..9ed63fd 100644 +--- a/modules/sca/sca_call_info.c ++++ b/modules/sca/sca_call_info.c +@@ -980,11 +980,13 @@ sca_call_info_invite_request_handler( sip_msg_t *msg, sca_call_info *call_info, + int state = SCA_APPEARANCE_STATE_UNKNOWN; + int rc = -1; + str *target_aor = from_aor; ++ int upstream = 0; + + if(SCA_CALL_INFO_IS_SHARED_CALLEE( call_info ) && + sca->rr_api->is_direction(msg, RR_FLOW_UPSTREAM)==0) { + LM_DBG("callee is SCA and direction is 'upstream'\n"); + target_aor = to_aor; ++ upstream = 1; + } + + /* +@@ -998,7 +1000,7 @@ sca_call_info_invite_request_handler( sip_msg_t *msg, sca_call_info *call_info, + goto done; + } + +- if ( !SCA_CALL_INFO_IS_SHARED_CALLER( call_info )) { ++ if ( !upstream && !SCA_CALL_INFO_IS_SHARED_CALLER( call_info )) { + /* caller isn't SCA, no more to do. update callee in reply handler. */ + rc = 1; + goto done; diff --git a/debian/patches/sipwise/sca-fix-pickup-when-upstream-flow.patch b/debian/patches/sipwise/sca-fix-pickup-when-upstream-flow.patch new file mode 100644 index 000000000..0a888d3d4 --- /dev/null +++ b/debian/patches/sipwise/sca-fix-pickup-when-upstream-flow.patch @@ -0,0 +1,120 @@ +From: Victor Seva +Date: Thu, 8 Jun 2017 16:13:03 +0200 +Subject: sca: fix pickup when upstream flow + +Change-Id: Ibed4c626573e3ac6d0fdc43a0f83954f17e60283 +--- + modules/sca/sca_call_info.c | 47 +++++++++++++++++++++++++++++---------------- + 1 file changed, 30 insertions(+), 17 deletions(-) + +diff --git a/modules/sca/sca_call_info.c b/modules/sca/sca_call_info.c +index cbd9b9b..370fcc2 100644 +--- a/modules/sca/sca_call_info.c ++++ b/modules/sca/sca_call_info.c +@@ -979,6 +979,13 @@ sca_call_info_invite_request_handler( sip_msg_t *msg, sca_call_info *call_info, + str state_str = STR_NULL; + int state = SCA_APPEARANCE_STATE_UNKNOWN; + int rc = -1; ++ str *target_aor = from_aor; ++ ++ if(SCA_CALL_INFO_IS_SHARED_CALLEE( call_info ) && ++ sca->rr_api->is_direction(msg, RR_FLOW_UPSTREAM)==0) { ++ LM_DBG("callee is SCA and direction is 'upstream'\n"); ++ target_aor = to_aor; ++ } + + /* + * if we get here, one of the legs is an SCA endpoint. we want to know +@@ -987,7 +994,7 @@ sca_call_info_invite_request_handler( sip_msg_t *msg, sca_call_info *call_info, + if ( sca->tm_api->register_tmcb( msg, NULL, TMCB_E2EACK_IN, + sca_call_info_ack_cb, NULL, NULL ) < 0 ) { + LM_ERR( "sca_call_info_invite_request_handler: failed to register " +- "callback for INVITE %.*s ACK", STR_FMT( from_aor )); ++ "callback for INVITE %.*s ACK", STR_FMT( target_aor )); + goto done; + } + +@@ -1005,7 +1012,7 @@ sca_call_info_invite_request_handler( sip_msg_t *msg, sca_call_info *call_info, + if ( sca->tm_api->register_tmcb( msg, NULL, TMCB_RESPONSE_READY, + sca_call_info_response_ready_cb, NULL, NULL ) < 0 ) { + LM_ERR( "sca_call_info_invite_request_handler: failed to register " +- "callback for INVITE %.*s ACK", STR_FMT( from_aor )); ++ "callback for INVITE %.*s ACK", STR_FMT( target_aor )); + goto done; + } + +@@ -1036,17 +1043,17 @@ sca_call_info_invite_request_handler( sip_msg_t *msg, sca_call_info *call_info, + return( -1 ); + } + +- if ( sca_appearance_update_index( sca, from_aor, call_info->index, ++ if ( sca_appearance_update_index( sca, target_aor, call_info->index, + state, NULL, NULL, &dialog ) != SCA_APPEARANCE_OK ) { + sca_appearance_state_to_str( state, &state_str ); + LM_ERR( "Failed to update %.*s appearance-index %d to %.*s", +- STR_FMT( from_aor ), call_info->index, ++ STR_FMT( target_aor ), call_info->index, + STR_FMT( &state_str )); + } + +- if ( sca_notify_call_info_subscribers( sca, from_aor ) < 0 ) { ++ if ( sca_notify_call_info_subscribers( sca, target_aor ) < 0 ) { + LM_ERR( "Failed to call-info NOTIFY %.*s subscribers on INVITE", +- STR_FMT( from_aor )); ++ STR_FMT( target_aor )); + goto done; + } + +@@ -1373,6 +1380,7 @@ sca_call_info_ack_from_handler( sip_msg_t *msg, str *from_aor, str *to_aor ) + str *tag; + int slot_idx = -1; + int state = SCA_APPEARANCE_STATE_IDLE; ++ str *target_aor; + + if ( sca_get_msg_from_header( msg, &from ) < 0 ) { + LM_ERR( "sca_call_info_ack_cb: failed to get From-header" ); +@@ -1383,18 +1391,23 @@ sca_call_info_ack_from_handler( sip_msg_t *msg, str *from_aor, str *to_aor ) + return; + } + +- if ( sca_uri_lock_if_shared_appearance( sca, from_aor, &slot_idx )) { +- if(sca->rr_api->is_direction(msg, RR_FLOW_UPSTREAM)==0) { +- LM_DBG("upstream direction detected\n"); +- tag = &to->tag_value; +- } else { +- tag = &from->tag_value; +- } +- app = sca_appearance_for_tags_unsafe( sca, from_aor, ++ if(sca->rr_api->is_direction(msg, RR_FLOW_UPSTREAM)==0) { ++ LM_DBG("upstream direction detected\n"); ++ target_aor = to_aor; ++ tag = &to->tag_value; ++ } else { ++ target_aor = from_aor; ++ tag = &from->tag_value; ++ } ++ ++ LM_DBG("target_aor[%.*s]\n", STR_FMT(target_aor)); ++ ++ if ( sca_uri_lock_if_shared_appearance( sca, target_aor, &slot_idx )) { ++ app = sca_appearance_for_tags_unsafe( sca, target_aor, + &msg->callid->body, tag, NULL, slot_idx ); + if ( app == NULL ) { + LM_ERR( "sca_call_info_ack_cb: No appearance for %.*s matching " +- "call-id <%.*s> and from-tag <%.*s>", STR_FMT( from_aor ), ++ "call-id <%.*s> and from-tag <%.*s>", STR_FMT( target_aor ), + STR_FMT( &msg->callid->body ), STR_FMT( tag )); + goto done; + } +@@ -1425,9 +1438,9 @@ done: + sca_hash_table_unlock_index( sca->appearances, slot_idx ); + + if ( state != SCA_APPEARANCE_STATE_IDLE ) { +- if ( sca_notify_call_info_subscribers( sca, from_aor ) < 0 ) { ++ if ( sca_notify_call_info_subscribers( sca, target_aor ) < 0 ) { + LM_ERR( "Failed to call-info NOTIFY %.*s subscribers on INVITE", +- STR_FMT( from_aor )); ++ STR_FMT( target_aor )); + } + } + } diff --git a/debian/patches/sipwise/sca-line-seize.patch b/debian/patches/sipwise/sca-line-seize.patch new file mode 100644 index 000000000..4aaf7125f --- /dev/null +++ b/debian/patches/sipwise/sca-line-seize.patch @@ -0,0 +1,629 @@ +From: Sipwise Development Team +Date: Thu, 16 Mar 2017 15:45:42 +0100 +Subject: sca: [to|from]_avp module parameters + +Change-Id: Ie7b09e95dd975fc549b1bb26e34663370200be0a +--- + modules/sca/sca.c | 102 +++++++++++++++++++++++++++++- + modules/sca/sca.h | 6 ++ + modules/sca/sca_call_info.c | 77 ++++++++++------------- + modules/sca/sca_subscribe.c | 52 +++++++++------- + modules/sca/sca_subscribe.h | 2 +- + modules/sca/sca_util.c | 148 +++++++++++++++++++++++++------------------- + 6 files changed, 255 insertions(+), 132 deletions(-) + +diff --git a/modules/sca/sca.c b/modules/sca/sca.c +index 9e03f6f..99d2ac1 100644 +--- a/modules/sca/sca.c ++++ b/modules/sca/sca.c +@@ -47,11 +47,22 @@ db_func_t dbf; /* db api */ + struct tm_binds tmb; /* tm functions for sending messages */ + sl_api_t slb; /* sl callback, function for getting to-tag */ + ++/* avps */ ++unsigned short from_uri_avp_type; ++int_str from_uri_avp; ++unsigned short to_uri_avp_type; ++int_str to_uri_avp; ++ + /* PROTOTYPES */ + static int sca_mod_init( void ); + static int sca_child_init( int ); + static void sca_mod_destroy( void ); + static int sca_set_config( sca_mod * ); ++static int sca_handle_subscribe_0_f(sip_msg_t* msg); ++static int sca_handle_subscribe_1_f(sip_msg_t* msg, char*); ++static int sca_handle_subscribe_2_f(sip_msg_t* msg, char*, char *); ++int fixup_hs(void **, int); ++int fixup_free_hs(void **param, int param_no); + static int sca_call_info_update_0_f(sip_msg_t* msg); + static int sca_call_info_update_1_f(sip_msg_t* msg, char*); + static int sca_call_info_update_2_f(sip_msg_t* msg, char* , char*); +@@ -61,7 +72,12 @@ int fixup_free_ciu(void **param, int param_no); + + /* EXPORTED COMMANDS */ + static cmd_export_t cmds[] = { +- { "sca_handle_subscribe", (cmd_function)sca_handle_subscribe, 0, NULL, NULL, REQUEST_ROUTE }, ++ { "sca_handle_subscribe", (cmd_function)sca_handle_subscribe_0_f, 0, ++ NULL, NULL, REQUEST_ROUTE }, ++ { "sca_handle_subscribe", (cmd_function)sca_handle_subscribe_1_f, 1, ++ fixup_hs, fixup_free_hs, REQUEST_ROUTE }, ++ { "sca_handle_subscribe", (cmd_function)sca_handle_subscribe_2_f, 2, ++ fixup_hs, fixup_free_hs, REQUEST_ROUTE }, + { "sca_call_info_update", (cmd_function)sca_call_info_update_0_f, 0, NULL, NULL, + REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE }, + {"sca_call_info_update", (cmd_function)sca_call_info_update_1_f, 1, +@@ -112,6 +128,8 @@ int line_seize_max_expires = 15; + int purge_expired_interval = 120; + int onhold_bflag = -1; + str server_address = STR_NULL; ++str from_uri_avp_param = STR_NULL; ++str to_uri_avp_param = STR_NULL; + + static param_export_t params[] = { + { "outbound_proxy", PARAM_STR, &outbound_proxy }, +@@ -125,6 +143,8 @@ static param_export_t params[] = { + { "purge_expired_interval", INT_PARAM, &purge_expired_interval }, + {"onhold_bflag", INT_PARAM, &onhold_bflag}, + {"server_address", PARAM_STR, &server_address}, ++ {"from_uri_avp", PARAM_STR, &from_uri_avp_param}, ++ {"to_uri_avp", PARAM_STR, &to_uri_avp_param}, + { NULL, 0, NULL }, + }; + +@@ -301,6 +321,31 @@ sca_child_init( int rank ) + return( 0 ); + } + ++static int ++sca_process_avps(str *avp_param, int_str *avp, unsigned short *avp_type) ++{ ++ pv_spec_t *avp_spec; ++ unsigned short avp_flags; ++ ++ if (avp_param && avp_param->len > 0) { ++ avp_spec = pv_cache_get(avp_param); ++ if (avp_spec==NULL|| avp_spec->type!=PVT_AVP) { ++ LM_ERR("malformed or non AVP definition <%.*s>\n", STR_FMT(avp_param)); ++ return -1; ++ } ++ ++ if (pv_get_avp_name(0, &(avp_spec->pvp), avp, &avp_flags) != 0) { ++ LM_ERR("invalid AVP definition <%.*s>\n", STR_FMT(avp_param)); ++ return -1; ++ } ++ *avp_type = avp_flags; ++ } else { ++ avp->s.s = NULL; ++ avp->s.len = 0; ++ } ++ return 0; ++} ++ + static int + sca_mod_init( void ) + { +@@ -363,6 +408,11 @@ sca_mod_init( void ) + */ + register_dummy_timers( 1 ); + ++ if(sca_process_avps(&from_uri_avp_param, &from_uri_avp, &from_uri_avp_type)<0 || ++ sca_process_avps(&to_uri_avp_param, &to_uri_avp, &to_uri_avp_type)<0) { ++ goto error; ++ } ++ + LM_INFO( "initialized" ); + + return( 0 ); +@@ -402,6 +452,56 @@ sca_mod_destroy( void ) + sca_db_disconnect(); + } + ++static int sca_handle_subscribe_0_f(sip_msg_t* msg) { ++ return sca_handle_subscribe(msg, NULL, NULL); ++} ++static int sca_handle_subscribe_1_f(sip_msg_t* msg, char* p1) { ++ str uri_to = STR_NULL; ++ if(get_str_fparam(&uri_to, msg, (gparam_p)p1)!=0) ++ { ++ LM_ERR("unable to get value from param pvar_to\n"); ++ return -1; ++ } ++ return sca_handle_subscribe(msg, &uri_to, NULL); ++} ++static int sca_handle_subscribe_2_f(sip_msg_t* msg, char* p1, char* p2) { ++ str uri_to = STR_NULL; ++ str uri_from = STR_NULL; ++ if(get_str_fparam(&uri_to, msg, (gparam_p)p1)!=0) ++ { ++ LM_ERR("unable to get value from param pvar_to\n"); ++ return -1; ++ } ++ if(get_str_fparam(&uri_from, msg, (gparam_p)p2)!=0) ++ { ++ LM_ERR("unable to get value from param pvar_from\n"); ++ return -1; ++ } ++return sca_handle_subscribe(msg, &uri_to, &uri_from); ++} ++ ++int fixup_hs(void **param, int param_no) ++{ ++ switch (param_no) { ++ case 1: ++ case 2: ++ return fixup_spve_null(param, 1); ++ default: ++ return E_UNSPEC; ++ } ++} ++ ++int fixup_free_hs(void **param, int param_no) ++{ ++ switch (param_no) { ++ case 1: ++ case 2: ++ return fixup_free_spve_null(param, 1); ++ default: ++ return E_UNSPEC; ++ } ++} ++ + static int sca_call_info_update_0_f(sip_msg_t* msg) { + return sca_call_info_update(msg, NULL, NULL, NULL); + } +diff --git a/modules/sca/sca.h b/modules/sca/sca.h +index abcbe56..69fed94 100644 +--- a/modules/sca/sca.h ++++ b/modules/sca/sca.h +@@ -55,4 +55,10 @@ typedef struct _sca_mod sca_mod; + + extern sca_mod *sca; + ++/* avps */ ++extern unsigned short from_uri_avp_type; ++extern int_str from_uri_avp; ++extern unsigned short to_uri_avp_type; ++extern int_str to_uri_avp; ++ + #endif /* SCA_H */ +diff --git a/modules/sca/sca_call_info.c b/modules/sca/sca_call_info.c +index d46c65d..734fbe2 100644 +--- a/modules/sca/sca_call_info.c ++++ b/modules/sca/sca_call_info.c +@@ -1874,12 +1874,12 @@ sca_call_info_update( sip_msg_t *msg, char *p1, str *uri_to, str *uri_from ) + str to_aor = STR_NULL; + str contact_uri = STR_NULL; + int aor_flags = SCA_CALL_INFO_UPDATE_FLAG_DEFAULT; +- int to_body_flags = SCA_CALL_INFO_UPDATE_FLAG_DEFAULT; + int n_dispatch; + int i; + int method; + int rc = -1; + int update_mask = SCA_CALL_INFO_SHARED_BOTH; ++ int_str val; + + method = sca_get_msg_method( msg ); + +@@ -1931,6 +1931,9 @@ sca_call_info_update( sip_msg_t *msg, char *p1, str *uri_to, str *uri_from ) + } + } + ++ delete_avp(from_uri_avp_type|AVP_VAL_STR, from_uri_avp); ++ delete_avp(to_uri_avp_type|AVP_VAL_STR, to_uri_avp); ++ + memset( &call_info, 0, sizeof( sca_call_info )); + call_info_hdr = sca_call_info_header_find( msg->headers ); + if ( !SCA_HEADER_EMPTY( call_info_hdr )) { +@@ -1943,36 +1946,22 @@ sca_call_info_update( sip_msg_t *msg, char *p1, str *uri_to, str *uri_from ) + } + + if (uri_from != NULL) { +- if(sca_build_to_body_from_uri(msg, &from, uri_from)<0){ +- LM_ERR( "Bad From uri from param\n" ); +- return( -1 ); +- } ++ val.s.s = uri_from->s; ++ val.s.len = uri_from->len; ++ add_avp(from_uri_avp_type|AVP_VAL_STR, from_uri_avp, val); + LM_DBG("from[%.*s] param\n", STR_FMT(uri_from)); +- to_body_flags |= SCA_CALL_INFO_UPDATE_FLAG_FROM_ALLOC; +- if ( sca_uri_extract_aor( &from->uri, &from_aor ) < 0 ) { +- LM_ERR( "Failed to extract AoR from From URI %.*s", +- STR_FMT( &from->uri )); +- goto done; +- } + } +- else if ( sca_get_msg_from_header( msg, &from ) < 0 ) { +- LM_ERR( "Bad From header" ); ++ if ( sca_get_msg_from_header( msg, &from ) < 0 ) { ++ LM_ERR( "Bad From header" ); + return( -1 ); + } + if (uri_to != NULL) { +- if(sca_build_to_body_from_uri(msg, &to, uri_to)<0){ +- LM_ERR( "Bad From uri to param\n" ); +- goto done; +- } ++ val.s.s = uri_to->s; ++ val.s.len = uri_to->len; ++ add_avp(to_uri_avp_type|AVP_VAL_STR, to_uri_avp, val); + LM_DBG("to[%.*s] param\n", STR_FMT(uri_to)); +- to_body_flags |= SCA_CALL_INFO_UPDATE_FLAG_TO_ALLOC; +- if ( sca_uri_extract_aor( &to->uri, &to_aor ) < 0 ) { +- LM_ERR( "Failed to extract AoR from To URI %.*s", +- STR_FMT( &to->uri )); +- goto done; +- } + } +- else if ( sca_get_msg_to_header( msg, &to ) < 0 ) { ++ if ( sca_get_msg_to_header( msg, &to ) < 0 ) { + LM_ERR( "Bad To header" ); + goto done; + } +@@ -2001,27 +1990,35 @@ sca_call_info_update( sip_msg_t *msg, char *p1, str *uri_to, str *uri_from ) + goto done; + } + aor_flags |= SCA_CALL_INFO_UPDATE_FLAG_FROM_ALLOC; +- } +- if(uri_to==NULL) { +- if ( sca_uri_extract_aor( &to->uri, &to_aor ) < 0 ) { +- LM_ERR( "Failed to extract AoR from To URI %.*s", +- STR_FMT( &to->uri )); +- goto done; +- } +- } +- } else { +- if(uri_from==NULL) { ++ } else { + if ( sca_uri_extract_aor( &from->uri, &from_aor ) < 0 ) { + LM_ERR( "Failed to extract AoR from From URI %.*s", +- STR_FMT( &from->uri )); ++ STR_FMT( &from->uri )); + goto done; + } + } ++ if ( sca_uri_extract_aor( &to->uri, &to_aor ) < 0 ) { ++ LM_ERR( "Failed to extract AoR from To URI %.*s", ++ STR_FMT( &to->uri )); ++ goto done; ++ } ++ } else { ++ if ( sca_uri_extract_aor( &from->uri, &from_aor ) < 0 ) { ++ LM_ERR( "Failed to extract AoR from From URI %.*s", ++ STR_FMT( &from->uri )); ++ goto done; ++ } + if(uri_to==NULL) { + if ( sca_create_canonical_aor( msg, &to_aor ) < 0 ) { + goto done; + } + aor_flags |= SCA_CALL_INFO_UPDATE_FLAG_TO_ALLOC; ++ } else { ++ if ( sca_uri_extract_aor( &to->uri, &to_aor ) < 0 ) { ++ LM_ERR( "Failed to extract AoR from To URI %.*s", ++ STR_FMT( &to->uri )); ++ goto done; ++ } + } + } + +@@ -2088,15 +2085,5 @@ done: + pkg_free( to_aor.s ); + } + } +- if (( to_body_flags & SCA_CALL_INFO_UPDATE_FLAG_FROM_ALLOC )) { +- if ( from != NULL ) { +- free_to( from ); +- } +- } +- if (( to_body_flags & SCA_CALL_INFO_UPDATE_FLAG_TO_ALLOC )) { +- if ( to != NULL ) { +- free_to( to ); +- } +- } + return( rc ); + } +diff --git a/modules/sca/sca_subscribe.c b/modules/sca/sca_subscribe.c +index 25fac54..3b92162 100644 +--- a/modules/sca/sca_subscribe.c ++++ b/modules/sca/sca_subscribe.c +@@ -1043,10 +1043,6 @@ sca_subscription_from_request( sca_mod *scam, sip_msg_t *msg, int event_type, + expires = max_expires; + } + +- if ( SCA_HEADER_EMPTY( msg->to )) { +- LM_ERR( "Empty To header" ); +- goto error; +- } + if ( SCA_HEADER_EMPTY( msg->callid )) { + LM_ERR( "Empty Call-ID header" ); + goto error; +@@ -1068,30 +1064,18 @@ sca_subscription_from_request( sca_mod *scam, sip_msg_t *msg, int event_type, + goto error; + } + +- if ( SCA_HEADER_EMPTY( msg->from )) { +- LM_ERR( "Empty From header" ); +- goto error; +- } +- if ( parse_from_header( msg ) < 0 ) { ++ if ( sca_get_msg_from_header( msg, &from ) < 0 ) { + LM_ERR( "Bad From header" ); + goto error; + } +- from = (struct to_body *)msg->from->parsed; + if ( SCA_STR_EMPTY( &from->tag_value )) { + LM_ERR( "No from-tag in From header" ); + goto error; + } + +- if (( to = (struct to_body *)msg->to->parsed ) == NULL ) { +- parse_to( msg->to->body.s, +- msg->to->body.s + msg->to->body.len + 1, /* end of buffer */ +- &tmp_to ); +- +- if ( tmp_to.error != PARSE_OK ) { +- LM_ERR( "Bad To header" ); +- goto error; +- } +- to = &tmp_to; ++ if ( sca_get_msg_to_header( msg, &to ) < 0 ) { ++ LM_ERR( "Bad To header" ); ++ goto error; + } + + if (parse_sip_msg_uri(msg) < 0) { +@@ -1179,7 +1163,7 @@ error: + } + + int +-sca_handle_subscribe( sip_msg_t *msg, char *p1, char *p2 ) ++sca_handle_subscribe( sip_msg_t *msg, str *uri_to, str *uri_from ) + { + sca_subscription req_sub; + sca_subscription *sub = NULL; +@@ -1194,6 +1178,8 @@ sca_handle_subscribe( sip_msg_t *msg, char *p1, char *p2 ) + int idx = -1; + int rc = -1; + int released = 0; ++ int_str val; ++ struct to_body *tmp_to; + + if ( parse_headers( msg, HDR_EOH_F, 0 ) < 0 ) { + LM_ERR( "header parsing failed: bad request" ); +@@ -1218,6 +1204,20 @@ sca_handle_subscribe( sip_msg_t *msg, char *p1, char *p2 ) + return( -1 ); + } + ++ delete_avp(from_uri_avp_type|AVP_VAL_STR, from_uri_avp); ++ delete_avp(to_uri_avp_type|AVP_VAL_STR, to_uri_avp); ++ if (uri_from != NULL) { ++ val.s.s = uri_from->s; ++ val.s.len = uri_from->len; ++ add_avp(from_uri_avp_type|AVP_VAL_STR, from_uri_avp, val); ++ LM_DBG("from[%.*s] param\n", STR_FMT(uri_from)); ++ } ++ if (uri_to != NULL) { ++ val.s.s = uri_to->s; ++ val.s.len = uri_to->len; ++ add_avp(to_uri_avp_type|AVP_VAL_STR, to_uri_avp, val); ++ LM_DBG("to[%.*s] param\n", STR_FMT(uri_to)); ++ } + if ( sca_subscription_from_request( sca, msg, event_type, &req_sub ) < 0 ) { + SCA_SUB_REPLY_ERROR( sca, 400, + "Bad Shared Call Appearance Request", msg ); +@@ -1231,7 +1231,15 @@ sca_handle_subscribe( sip_msg_t *msg, char *p1, char *p2 ) + sca_subscription_print( &req_sub ); + + /* check to see if the message has a to-tag */ +- to_tag = &(get_to( msg )->tag_value); ++ if(uri_to!=NULL) { ++ if ( sca_get_msg_to_header( msg, &tmp_to ) < 0 ) { ++ LM_ERR( "Bad To header" ); ++ return( -1 ); ++ } ++ to_tag = &(tmp_to->tag_value); ++ } else { ++ to_tag = &(get_to( msg )->tag_value); ++ } + + /* XXX should lock starting here and use unsafe methods below? */ + +diff --git a/modules/sca/sca_subscribe.h b/modules/sca/sca_subscribe.h +index a3688de..6e4b381 100644 +--- a/modules/sca/sca_subscribe.h ++++ b/modules/sca/sca_subscribe.h +@@ -75,7 +75,7 @@ extern const str SCA_METHOD_SUBSCRIBE; + sca_subscription_reply((mod), (scode), (smsg), \ + SCA_EVENT_TYPE_CALL_INFO, -1, (sreply)) + +-int sca_handle_subscribe( sip_msg_t *, char *, char * ); ++int sca_handle_subscribe( sip_msg_t *, str *, str * ); + int sca_subscription_reply( sca_mod *, int, char *, int, int, sip_msg_t * ); + + int sca_subscription_from_db_result( db1_res_t *, sca_subscription * ); +diff --git a/modules/sca/sca_util.c b/modules/sca/sca_util.c +index 32a20bc..a3476d8 100644 +--- a/modules/sca/sca_util.c ++++ b/modules/sca/sca_util.c +@@ -116,94 +116,116 @@ sca_get_msg_cseq_method( sip_msg_t *msg ) + + /* caller needs to call free_to for *body */ + int +-sca_build_to_body_from_uri(sip_msg_t *msg, struct to_body **body, str *uri) ++sca_parse_uri(struct to_body *body, str *uri) + { +- assert( msg != NULL ); + assert( body != NULL ); + assert( uri != NULL ); + +- *body = pkg_malloc(sizeof(struct to_body)); +- if(*body == NULL) { +- LM_ERR("cannot allocate pkg memory\n"); +- return(-1); +- } +- +- parse_to(uri->s, uri->s + uri->len + 1, *body); +- if ((*body)->error != PARSE_OK) { ++ parse_to(uri->s, uri->s + uri->len + 1, body); ++ if (body->error != PARSE_OK) { + LM_ERR("Bad uri value[%.*s]\n", STR_FMT(uri)); +- free_to(*body); + return(-1); + } + return (0); + } + +- int +-sca_get_msg_from_header( sip_msg_t *msg, struct to_body **from ) +-{ +- struct to_body *f; ++int ++sca_get_avp_value(unsigned short avp_type, int_str avp, str *result) { ++ int_str val; ++ struct usr_avp *_avp; ++ ++ assert(result != NULL); ++ ++ if (avp.s.len > 0) { ++ _avp = search_first_avp(avp_type, avp, &val, 0); ++ if(_avp) { ++ result->s = val.s.s; ++ result->len = val.s.len; ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++int ++sca_get_msg_from_header( sip_msg_t *msg, struct to_body **from ) { ++ struct to_body *f; ++ static struct to_body sf; ++ str uri = STR_NULL; + +- assert( msg != NULL ); + assert( from != NULL ); + +- if ( SCA_HEADER_EMPTY( msg->from )) { +- LM_ERR( "Empty From header" ); +- return( -1 ); +- } +- if ( parse_from_header( msg ) < 0 ) { +- LM_ERR( "Bad From header" ); +- return( -1 ); +- } +- f = get_from( msg ); +- if ( SCA_STR_EMPTY( &f->tag_value )) { +- LM_ERR( "Bad From header: no tag parameter" ); +- return( -1 ); +- } ++ if(sca_get_avp_value(from_uri_avp_type, from_uri_avp, &uri)<0) { ++ assert( msg != NULL ); ++ if ( SCA_HEADER_EMPTY( msg->from )) { ++ LM_ERR( "Empty From header" ); ++ return( -1 ); ++ } ++ if ( parse_from_header( msg ) < 0 ) { ++ LM_ERR( "Bad From header" ); ++ return( -1 ); ++ } ++ f = get_from( msg ); ++ if ( SCA_STR_EMPTY( &f->tag_value )) { ++ LM_ERR( "Bad From header: no tag parameter" ); ++ return( -1 ); ++ } + +- /* ensure the URI is parsed for future use */ +- if ( parse_uri( f->uri.s, f->uri.len, GET_FROM_PURI( msg )) < 0 ) { +- LM_ERR( "Failed to parse From URI %.*s", STR_FMT( &f->uri )); +- return( -1 ); ++ /* ensure the URI is parsed for future use */ ++ if ( parse_uri( f->uri.s, f->uri.len, GET_FROM_PURI( msg )) < 0 ) { ++ LM_ERR( "Failed to parse From URI %.*s", STR_FMT( &f->uri )); ++ return( -1 ); ++ } ++ *from = f; ++ } else { ++ LM_DBG("using $avp(%.*s)[%.*s] as from uri\n", ++ STR_FMT(&from_uri_avp.s), STR_FMT(&uri)); ++ if(sca_parse_uri(&sf, &uri)<0) return -1; ++ *from = &sf; + } +- +- *from = f; +- +- return( 0 ); ++ return ( 0 ); + } + +- int ++int + sca_get_msg_to_header( sip_msg_t *msg, struct to_body **to ) + { +- struct to_body parsed_to; ++ static struct to_body parsed_to; + struct to_body *t = NULL; ++ str uri = STR_NULL; + +- assert( msg != NULL ); + assert( to != NULL ); ++ if(sca_get_avp_value(to_uri_avp_type, to_uri_avp, &uri)<0) { ++ assert( msg != NULL ); + +- if ( SCA_HEADER_EMPTY( msg->to )) { +- LM_ERR( "Empty To header" ); +- return( -1 ); +- } +- t = get_to( msg ); +- if ( t == NULL ) { +- parse_to( msg->to->body.s, +- msg->to->body.s + msg->to->body.len + 1, /* end of buffer */ +- &parsed_to ); +- if ( parsed_to.error != PARSE_OK ) { +- LM_ERR( "Bad To header" ); +- return( -1 ); +- } +- t = &parsed_to; +- } ++ if ( SCA_HEADER_EMPTY( msg->to )) { ++ LM_ERR( "Empty To header" ); ++ return( -1 ); ++ } ++ t = get_to( msg ); ++ if ( t == NULL ) { ++ parse_to( msg->to->body.s, ++ msg->to->body.s + msg->to->body.len + 1, /* end of buffer */ ++ &parsed_to ); ++ if ( parsed_to.error != PARSE_OK ) { ++ LM_ERR( "Bad To header" ); ++ return( -1 ); ++ } ++ t = &parsed_to; ++ } + +- /* ensure the URI is parsed for future use */ +- if ( parse_uri( t->uri.s, t->uri.len, GET_TO_PURI( msg )) < 0 ) { +- LM_ERR( "Failed to parse To URI %.*s", STR_FMT( &t->uri )); +- return( -1 ); ++ /* ensure the URI is parsed for future use */ ++ if ( parse_uri( t->uri.s, t->uri.len, GET_TO_PURI( msg )) < 0 ) { ++ LM_ERR( "Failed to parse To URI %.*s", STR_FMT( &t->uri )); ++ return( -1 ); ++ } ++ *to = t; ++ } else { ++ LM_DBG("using $avp(%.*s)[%.*s] as to uri\n", ++ STR_FMT(&to_uri_avp.s), STR_FMT(&uri)); ++ if(sca_parse_uri(&parsed_to, &uri)<0) return -1; ++ *to = &parsed_to; + } +- +- *to = t; +- +- return( 0 ); ++ return ( 0 ); + } + + /* count characters requiring escape as defined by escape_common */ diff --git a/debian/patches/sipwise/sca-rr-is-direction.patch b/debian/patches/sipwise/sca-rr-is-direction.patch new file mode 100644 index 000000000..3e41ad42e --- /dev/null +++ b/debian/patches/sipwise/sca-rr-is-direction.patch @@ -0,0 +1,183 @@ +From: Victor Seva +Date: Thu, 20 Apr 2017 12:19:08 +0200 +Subject: sca: use rr is_direction() to detect which tag to use for search + +Change-Id: I17ac925867ce5897b7db93729a4e29edcefe922a +--- + modules/sca/sca.c | 10 +++++++++- + modules/sca/sca.h | 1 + + modules/sca/sca_call_info.c | 47 +++++++++++++++++++++++++++++++++++++-------- + modules/sca/sca_common.h | 1 + + 4 files changed, 50 insertions(+), 9 deletions(-) + +diff --git a/modules/sca/sca.c b/modules/sca/sca.c +index 99d2ac1..f8010e9 100644 +--- a/modules/sca/sca.c ++++ b/modules/sca/sca.c +@@ -45,7 +45,9 @@ sca_mod *sca = NULL; + /* EXTERNAL API */ + db_func_t dbf; /* db api */ + struct tm_binds tmb; /* tm functions for sending messages */ +-sl_api_t slb; /* sl callback, function for getting to-tag */ ++struct rr_binds rrb; /* rr functions for detecting direction */ ++sl_api_t slb; /* sl callback, function for getting to-tag */ ++ + + /* avps */ + unsigned short from_uri_avp_type; +@@ -377,6 +379,12 @@ sca_mod_init( void ) + } + sca->tm_api = &tmb; + ++ if ( load_rr_api( &rrb ) != 0 ) { ++ LM_ERR( "Failed to initialize required rr API" ); ++ goto error; ++ } ++ sca->rr_api = &rrb; ++ + if ( sca_bind_sl( sca, &slb ) != 0 ) { + LM_ERR( "Failed to initialize required sl API" ); + goto error; +diff --git a/modules/sca/sca.h b/modules/sca/sca.h +index 69fed94..3dee96b 100644 +--- a/modules/sca/sca.h ++++ b/modules/sca/sca.h +@@ -49,6 +49,7 @@ struct _sca_mod { + + db_func_t *db_api; + struct tm_binds *tm_api; ++ struct rr_binds *rr_api; + sl_api_t *sl_api; + }; + typedef struct _sca_mod sca_mod; +diff --git a/modules/sca/sca_call_info.c b/modules/sca/sca_call_info.c +index 5592a68..cbd9b9b 100644 +--- a/modules/sca/sca_call_info.c ++++ b/modules/sca/sca_call_info.c +@@ -1370,6 +1370,7 @@ sca_call_info_ack_from_handler( sip_msg_t *msg, str *from_aor, str *to_aor ) + sca_appearance *app; + struct to_body *from; + struct to_body *to; ++ str *tag; + int slot_idx = -1; + int state = SCA_APPEARANCE_STATE_IDLE; + +@@ -1383,15 +1384,21 @@ sca_call_info_ack_from_handler( sip_msg_t *msg, str *from_aor, str *to_aor ) + } + + if ( sca_uri_lock_if_shared_appearance( sca, from_aor, &slot_idx )) { ++ if(sca->rr_api->is_direction(msg, RR_FLOW_UPSTREAM)==0) { ++ LM_DBG("upstream direction detected\n"); ++ tag = &to->tag_value; ++ } else { ++ tag = &from->tag_value; ++ } + app = sca_appearance_for_tags_unsafe( sca, from_aor, +- &msg->callid->body, &from->tag_value, NULL, slot_idx ); ++ &msg->callid->body, tag, NULL, slot_idx ); + if ( app == NULL ) { + LM_ERR( "sca_call_info_ack_cb: No appearance for %.*s matching " + "call-id <%.*s> and from-tag <%.*s>", STR_FMT( from_aor ), +- STR_FMT( &msg->callid->body ), STR_FMT( &from->tag_value )); ++ STR_FMT( &msg->callid->body ), STR_FMT( tag )); + goto done; + } +- ++ + /* + * Polycom's music-on-hold implementation uses an INVITE with + * an empty body to get the remote party's SDP info, then INVITEs +@@ -1430,11 +1437,12 @@ done: + void + sca_call_info_ack_cb( struct cell *t, int type, struct tmcb_params *params ) + { +- struct to_body *to; ++ struct to_body *to, *from; + sca_appearance *app = NULL; + str from_aor = STR_NULL; + str to_aor = STR_NULL; + int slot_idx = -1; ++ str *tag; + + if ( !(type & TMCB_E2EACK_IN)) { + return; +@@ -1463,8 +1471,18 @@ sca_call_info_ack_cb( struct cell *t, int type, struct tmcb_params *params ) + } + + /* on ACK, ensure SCA callee state is promoted to ACTIVE. */ ++ if(sca->rr_api->is_direction(params->req, RR_FLOW_UPSTREAM)==0) { ++ LM_DBG("upstream direction detected\n"); ++ if ( sca_get_msg_from_header( params->req, &from ) < 0 ) { ++ LM_ERR( "failed to get From-header" ); ++ goto done; ++ } ++ tag = &from->tag_value; ++ } else { ++ tag = &to->tag_value; ++ } + app = sca_appearance_for_tags_unsafe( sca, &to_aor, +- ¶ms->req->callid->body, &to->tag_value, NULL, slot_idx ); ++ ¶ms->req->callid->body, tag, NULL, slot_idx ); + if ( app && app->state == SCA_APPEARANCE_STATE_ACTIVE_PENDING ) { + LM_DBG( "promoting %.*s appearance-index %d to active", + STR_FMT( &to_aor ), app->index ); +@@ -1550,6 +1568,7 @@ sca_call_info_bye_handler( sip_msg_t *msg, sca_call_info *call_info, + sca_appearance *app = NULL; + int slot_idx = -1; + int rc = -1; ++ str *tag = NULL; + + if ( msg->first_line.type == SIP_REQUEST ) { + if ( SCA_CALL_INFO_IS_SHARED_CALLER( call_info )) { +@@ -1567,15 +1586,21 @@ sca_call_info_bye_handler( sip_msg_t *msg, sca_call_info *call_info, + } + if ( app == NULL ) { + /* try to find it by tags */ ++ if(sca->rr_api->is_direction(msg, RR_FLOW_UPSTREAM)==0) { ++ LM_DBG("upstream direction detected\n"); ++ tag = &to->tag_value; ++ } else { ++ tag = &from->tag_value; ++ } + app = sca_appearance_for_tags_unsafe( sca, from_aor, +- &msg->callid->body, &from->tag_value, NULL, slot_idx ); ++ &msg->callid->body, tag, NULL, slot_idx ); + } + if ( app == NULL ) { + LM_ERR( "sca_call_info_bye_handler: %.*s " + "dialog leg %.*s;%.*s is not active", + STR_FMT( from_aor ), + STR_FMT( &msg->callid->body ), +- STR_FMT( &from->tag_value )); ++ STR_FMT( tag )); + goto done; + } + +@@ -1615,8 +1640,14 @@ sca_call_info_bye_handler( sip_msg_t *msg, sca_call_info *call_info, + goto done; + } + ++ if(sca->rr_api->is_direction(msg, RR_FLOW_UPSTREAM)==0) { ++ LM_DBG("upstream direction detected\n"); ++ tag = &from->tag_value; ++ } else { ++ tag = &to->tag_value; ++ } + app = sca_appearance_for_tags_unsafe( sca, to_aor, +- &msg->callid->body, &to->tag_value, ++ &msg->callid->body, tag, + NULL, slot_idx ); + if ( app == NULL ) { + LM_INFO( "sca_call_info_bye_handler: no in-use callee " +diff --git a/modules/sca/sca_common.h b/modules/sca/sca_common.h +index 8b9db4a..2fbcc63 100644 +--- a/modules/sca/sca_common.h ++++ b/modules/sca/sca_common.h +@@ -49,6 +49,7 @@ + /* bound API headers */ + #include "../../modules/sl/sl.h" + #include "../../modules/tm/tm_load.h" ++#include "../../modules/rr/api.h" + + + /* convenience macros */