From: Sipwise Development Team <support@sipwise.com>
Date: Thu, 26 Mar 2020 10:06:46 +0100
Subject: sca-rr-is-direction

---
 src/modules/sca/sca.c           |  7 +++++
 src/modules/sca/sca.h           |  1 +
 src/modules/sca/sca_call_info.c | 59 +++++++++++++++++++++++++++++++++--------
 src/modules/sca/sca_common.h    |  1 +
 4 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/src/modules/sca/sca.c b/src/modules/sca/sca.c
index c2347bb..c0042b9 100644
--- a/src/modules/sca/sca.c
+++ b/src/modules/sca/sca.c
@@ -62,6 +62,7 @@ sca_mod *sca = NULL;
  */
 db_func_t dbf;		 // db api
 struct tm_binds tmb; // tm functions for sending messages
+struct rr_binds rrb; // rr functions for detecting direction
 sl_api_t slb;		 // sl callback, function for getting to-tag
 
 /* avps */
@@ -405,6 +406,12 @@ static int 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. Check that the \"sl\" "
 			   "module is loaded before this module.\n");
diff --git a/src/modules/sca/sca.h b/src/modules/sca/sca.h
index 7a80847..3d08921 100644
--- a/src/modules/sca/sca.h
+++ b/src/modules/sca/sca.h
@@ -51,6 +51,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/src/modules/sca/sca_call_info.c b/src/modules/sca/sca_call_info.c
index d83fe48..8734d3a 100644
--- a/src/modules/sca/sca_call_info.c
+++ b/src/modules/sca/sca_call_info.c
@@ -1362,6 +1362,7 @@ void sca_call_info_ack_from_handler(sip_msg_t *msg, str *from_aor, str *to_aor)
 {
 	sca_appearance *app;
 	sca_to_body_t from, to;
+	str *tag;
 	int slot_idx = -1;
 	int state = SCA_APPEARANCE_STATE_IDLE;
 
@@ -1378,13 +1379,19 @@ void 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)) {
-		app = sca_appearance_for_tags_unsafe(sca, from_aor, &msg->callid->body,
-				&from.hdr->tag_value, NULL, slot_idx);
+		if(sca->rr_api->is_direction(msg, RR_FLOW_UPSTREAM) == 0) {
+			LM_DBG("upstream direction detected\n");
+			tag = &to.hdr->tag_value;
+		} else {
+			tag = &from.hdr->tag_value;
+		}
+		app = sca_appearance_for_tags_unsafe(
+				sca, from_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>\n",
 					STR_FMT(from_aor), STR_FMT(&msg->callid->body),
-					STR_FMT(&from.hdr->tag_value));
+					STR_FMT(tag));
 			goto done;
 		}
 
@@ -1429,11 +1436,15 @@ done:
 /* XXX needs extract routines */
 void sca_call_info_ack_cb(struct cell *t, int type, struct tmcb_params *params)
 {
-	sca_to_body_t to;
+	sca_to_body_t to, from;
 	sca_appearance *app = NULL;
 	str from_aor = STR_NULL;
 	str to_aor = STR_NULL;
 	int slot_idx = -1;
+	str *tag;
+
+	memset(&to, 0, sizeof(sca_to_body_t));
+	memset(&from, 0, sizeof(sca_to_body_t));
 
 	memset(&to, 0, sizeof(to));
 
@@ -1464,8 +1475,18 @@ void sca_call_info_ack_cb(struct cell *t, int type, struct tmcb_params *params)
 	}
 
 	// on ACK, ensure SCA callee state is promoted to ACTIVE.
-	app = sca_appearance_for_tags_unsafe(sca, &to_aor,
-			&params->req->callid->body, &to.hdr->tag_value, NULL, slot_idx);
+	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.hdr->tag_value;
+	} else {
+		tag = &to.hdr->tag_value;
+	}
+	app = sca_appearance_for_tags_unsafe(
+			sca, &to_aor, &params->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\n",
 				STR_FMT(&to_aor), app->index);
@@ -1487,6 +1508,9 @@ done:
 	if(from_aor.s != NULL) {
 		pkg_free(from_aor.s);
 	}
+	if(from.flags & SCA_UTIL_FLAG_TO_BODY_ALLOC) {
+		free_to(from.hdr);
+	}
 	if(to.flags & SCA_UTIL_FLAG_TO_BODY_ALLOC) {
 		free_to(to.hdr);
 	}
@@ -1551,6 +1575,7 @@ static int 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)) {
@@ -1568,14 +1593,20 @@ static int sca_call_info_bye_handler(sip_msg_t *msg, sca_call_info *call_info,
 			}
 			if(app == NULL) {
 				// try to find it by tags
-				app = sca_appearance_for_tags_unsafe(sca, from_aor,
-						&msg->callid->body, &from->tag_value, NULL, 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, tag, NULL, slot_idx);
 			}
 			if(app == NULL) {
 				LM_ERR("sca_call_info_bye_handler: %.*s "
 					   "dialog leg %.*s;%.*s is not active\n",
 						STR_FMT(from_aor), STR_FMT(&msg->callid->body),
-						STR_FMT(&from->tag_value));
+						STR_FMT(tag));
 				goto done;
 			}
 
@@ -1616,8 +1647,14 @@ static int sca_call_info_bye_handler(sip_msg_t *msg, sca_call_info *call_info,
 				goto done;
 			}
 
-			app = sca_appearance_for_tags_unsafe(sca, to_aor,
-					&msg->callid->body, &to->tag_value, NULL, slot_idx);
+			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, tag, NULL, slot_idx);
 			if(app == NULL) {
 				LM_INFO("sca_call_info_bye_handler: no in-use callee "
 						"appearance for BYE %.*s from %.*s, call-ID %.*s\n",
diff --git a/src/modules/sca/sca_common.h b/src/modules/sca/sca_common.h
index 5c4520a..3a7c1b4 100644
--- a/src/modules/sca/sca_common.h
+++ b/src/modules/sca/sca_common.h
@@ -47,6 +47,7 @@
 // bound API headers
 #include "../../modules/sl/sl.h"
 #include "../../modules/tm/tm_load.h"
+#include "../../modules/rr/api.h"
 
 // convenience macros
 #define SCA_STRUCT_PTR_OFFSET(struct1, cast1, offset1) \
