Przeglądaj źródła

modules/interconnectroute: new methods: ix_orig_trunk_query() ix_term_trunk_query()
ix_orig_trunk_query(): get interconnect route and charging information for orig leg
ix_term_trunk_query(external_id): get interconnect charging information for term leg

Richard Good 10 lat temu
rodzic
commit
245774ddbe

+ 1 - 0
modules/interconnectroute/Makefile

@@ -13,5 +13,6 @@ DEFS+=-DKAMAILIO_MOD_INTERFACE
 
 
 SERLIBPATH=../../lib
 SERLIBPATH=../../lib
 SER_LIBS+=$(SERLIBPATH)/trie/trie $(SERLIBPATH)/srdb1/srdb1 $(SERLIBPATH)/kmi/kmi $(SERLIBPATH)/kcore/kcore
 SER_LIBS+=$(SERLIBPATH)/trie/trie $(SERLIBPATH)/srdb1/srdb1 $(SERLIBPATH)/kmi/kmi $(SERLIBPATH)/kcore/kcore
+SER_LIBS+=$(SERLIBPATH)/ims/kamailio_ims
 
 
 include ../../Makefile.modules
 include ../../Makefile.modules

+ 141 - 41
modules/interconnectroute/db.c

@@ -4,17 +4,40 @@
 db1_con_t * interconnectroute_dbh = NULL;
 db1_con_t * interconnectroute_dbh = NULL;
 db_func_t interconnectroute_dbf;
 db_func_t interconnectroute_dbf;
 
 
-static char *query_fmt = "select N.OPERATOR_KEY, T.TRUNK_ID, T.PRIORITY, T.IPV4, T.EXTERNAL_TRUNK_ID "
-	"from operator_number N left join operator_trunk T on N.OPERATOR_KEY=T.OPERATOR_KEY "
-	"where %.*s >= CAST(NUMBER_START AS UNSIGNED) and %.*s <= CAST(NUMBER_END AS UNSIGNED) ORDER BY T.PRIORITY DESC";
+static char *orig_route_data_query = "select TFROM.INTERNAL_ID as FROM_TRUNK_ID, TTO.INTERNAL_ID as TO_TRUNK_ID, RT.ROUTE_ID as ROUTE_ID from "
+    "service_rate SR "
+    "join interconnect_trunk TFROM on TFROM.INTERCONNECT_PARTNER_ID = SR.FROM_INTERCONNECT_PARTNER_ID "
+    "join interconnect_trunk TTO on TTO.INTERCONNECT_PARTNER_ID = SR.TO_INTERCONNECT_PARTNER_ID " 
+    "join interconnect_route RT on TTO.EXTERNAL_ID = RT.EXTERNAL_ID "
+    "where "
+    "%.*s >= SR.FROM_START "
+    "and %.*s <= SR.FROM_END "
+    "and %.*s >= SR.TO_START "
+    "and %.*s <= SR.TO_END "
+    "and SR.SERVICE_CODE = '%.*s' "
+    "and SR.LEG = '%.*s' "
+    "order by SR.PRIORITY DESC, RT.PRIORITY DESC LIMIT 1";
+
+static char *term_route_data_query = "select TFROM.INTERNAL_ID as FROM_TRUNK_ID, TTO.INTERNAL_ID as TO_TRUNK_ID from "
+    "service_rate SR "
+    "join interconnect_trunk TFROM on TFROM.INTERCONNECT_PARTNER_ID = SR.FROM_INTERCONNECT_PARTNER_ID "
+    "join interconnect_trunk TTO on TTO.INTERCONNECT_PARTNER_ID = SR.TO_INTERCONNECT_PARTNER_ID "
+    "where "
+    "%.*s >= SR.TO_START "
+    "and %.*s <= SR.TO_END "
+    "and %.*s >= SR.FROM_START "
+    "and %.*s <= SR.FROM_END "
+    "and SR.SERVICE_CODE = '%.*s' "
+    "and SR.LEG = '%.*s' "
+    "and TFROM.EXTERNAL_ID = '%.*s';";
+
 static char query[QUERY_LEN];
 static char query[QUERY_LEN];
 
 
-str interconnectnumber_table = str_init("operator_number");
 
 
-/* table version */
-const unsigned int interconnectroute_version = 1;
+str interconnect_trunk_table = str_init("interconnect_trunk");
+str interconnect_route_table = str_init("interconnect_route");
+str service_rate_table = str_init("service_rate");
 
 
-str interconnecttrunk_table = str_init("operator_trunk");
 
 
 /*
 /*
  * Closes the DB connection.
  * Closes the DB connection.
@@ -40,13 +63,6 @@ int interconnectroute_db_init(void) {
 	LM_ERR("can't connect to database using [%.*s]\n", interconnectroute_db_url.len, interconnectroute_db_url.s);
 	LM_ERR("can't connect to database using [%.*s]\n", interconnectroute_db_url.len, interconnectroute_db_url.s);
 	return -1;
 	return -1;
     }
     }
-    if (
-	    (db_check_table_version(&interconnectroute_dbf, interconnectroute_dbh, &interconnectnumber_table, interconnectroute_version) < 0) ||
-	    (db_check_table_version(&interconnectroute_dbf, interconnectroute_dbh, &interconnecttrunk_table, interconnectroute_version) < 0)) {
-	LM_ERR("during table version check.\n");
-	interconnectroute_db_close();
-	return -1;
-    }
     interconnectroute_db_close();
     interconnectroute_db_close();
     return 0;
     return 0;
 }
 }
@@ -63,35 +79,37 @@ int interconnectroute_db_open(void) {
     return 0;
     return 0;
 }
 }
 
 
-int get_routes(str* dst_number, route_data_t** route_data) {
-    int i,n, priority;
+
+int get_orig_route_data(str* a_number, str* b_number, str* leg, str* sc, ix_route_list_t** ix_route_list) {
+    int i,n;
     db1_res_t* route_rs;
     db1_res_t* route_rs;
     db_row_t* route_row;
     db_row_t* route_row;
     db_val_t* route_vals;
     db_val_t* route_vals;
-    str query_s, operator_key, trunk_id, external_trunk_id, gateway_ipv4;
+    str query_s, incoming_trunk_id, outgoing_trunk_id, route_id;
     route_data_t* new_route;
     route_data_t* new_route;
     ix_route_list_t* route_list = new_route_list();
     ix_route_list_t* route_list = new_route_list();
     int num_rows;
     int num_rows;
     
     
 
 
-    if (strlen(query_fmt) + dst_number->len > QUERY_LEN) {
+    if (strlen(orig_route_data_query) + a_number->len + a_number->len + b_number->len + b_number->len + leg->len + sc->len > QUERY_LEN) {
 	LM_ERR("query too big\n");
 	LM_ERR("query too big\n");
 	return -1;
 	return -1;
     }
     }
-    snprintf(query, QUERY_LEN, query_fmt, dst_number->len, dst_number->s, dst_number->len, dst_number->s);
+    
+    snprintf(query, QUERY_LEN, orig_route_data_query, a_number->len, a_number->s, a_number->len, a_number->s, b_number->len, b_number->s,
+	    b_number->len, b_number->s, sc->len, sc->s, leg->len, leg->s);
     query_s.s = query;
     query_s.s = query;
     query_s.len = strlen(query);
     query_s.len = strlen(query);
 
 
-    LM_DBG("QUERY IS: [%s]\n", query);
-
+    LM_DBG("get_orig_route_data query is: [%s]\n", query);
     if (interconnectroute_dbf.raw_query(interconnectroute_dbh, &query_s, &route_rs) != 0) {
     if (interconnectroute_dbf.raw_query(interconnectroute_dbh, &query_s, &route_rs) != 0) {
-	LM_ERR("Unable to query DB for interconnect routes with number [%.*s]\n", dst_number->len, dst_number->s);
+	LM_ERR("Unable to query DB for interconnect routes with a_number [%.*s] b_number [%.*s]\n", a_number->len, a_number->s, b_number->len, b_number->s);
 	interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
 	interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
     }
     }
 
 
     LM_DBG("Received route results [%d]\n", RES_ROW_N(route_rs));
     LM_DBG("Received route results [%d]\n", RES_ROW_N(route_rs));
     if (RES_ROW_N(route_rs) <= 0) {
     if (RES_ROW_N(route_rs) <= 0) {
-	LM_DBG("No routes found for number [%.*s]\n", dst_number->len, dst_number->s);
+	LM_DBG("No routes found for a_number [%.*s] b_number [%.*s]\n", a_number->len, a_number->s, b_number->len, b_number->s);
 	return -1;
 	return -1;
     } else {
     } else {
 	n = 0;
 	n = 0;
@@ -103,31 +121,112 @@ int get_routes(str* dst_number, route_data_t** route_data) {
 		route_vals = ROW_VALUES(route_row);
 		route_vals = ROW_VALUES(route_row);
 
 
 		if (!VAL_NULL(route_vals)) {
 		if (!VAL_NULL(route_vals)) {
-		    operator_key.s = (char*) VAL_STRING(route_vals);
-		    operator_key.len = strlen(operator_key.s);
-		    LM_DBG("Received route for operator key: [%.*s]\n", operator_key.len, operator_key.s);
+		    incoming_trunk_id.s = (char*) VAL_STRING(route_vals);
+		    incoming_trunk_id.len = strlen(incoming_trunk_id.s);
+		    LM_DBG("incoming_trunk_id: [%.*s]\n", incoming_trunk_id.len, incoming_trunk_id.s);
 		}
 		}
 		if (!VAL_NULL(route_vals+1)) {
 		if (!VAL_NULL(route_vals+1)) {
-		    trunk_id.s = (char*) VAL_STRING(route_vals+1);
-		    trunk_id.len = strlen(trunk_id.s);
-		    LM_DBG("Trunk is: [%.*s]\n", trunk_id.len, trunk_id.s);
+		    outgoing_trunk_id.s = (char*) VAL_STRING(route_vals+1);
+		    outgoing_trunk_id.len = strlen(outgoing_trunk_id.s);
+		    LM_DBG("outgoing_trunk_id: [%.*s]\n", outgoing_trunk_id.len, outgoing_trunk_id.s);
 		}
 		}
 		if (!VAL_NULL(route_vals+2)) {
 		if (!VAL_NULL(route_vals+2)) {
-		    priority = VAL_INT(route_vals+2);
-		    LM_DBG("Priority is: [%d]\n", priority);
+		    route_id.s = (char*) VAL_STRING(route_vals+2);
+		    route_id.len = strlen(route_id.s);
+		    LM_DBG("route_id: [%.*s]\n", route_id.len, route_id.s);
+		}
+		
+		new_route = new_route_data(&incoming_trunk_id, &outgoing_trunk_id, &route_id);
+		if (!new_route) {
+		    LM_DBG("Could not get new route... continuing\n");
+		    continue;
 		}
 		}
-		if (!VAL_NULL(route_vals+3)) {
-		    gateway_ipv4.s = (char*) VAL_STRING(route_vals+3);
-		    gateway_ipv4.len = strlen(gateway_ipv4.s);
-		    LM_DBG("Gateway IP for trunk to this operator is: [%.*s]\n", gateway_ipv4.len, gateway_ipv4.s);
+		
+		if (!add_route(route_list, new_route)) {
+		    LM_DBG("unable to add route.....\n");
+		    continue;
 		}
 		}
-		if (!VAL_NULL(route_vals+4)) {
-		    external_trunk_id.s = (char*) VAL_STRING(route_vals+4);
-		    external_trunk_id.len = strlen(external_trunk_id.s);
-		    LM_DBG("External trunk ID: [%.*s]\n", external_trunk_id.len, external_trunk_id.s);
+		
+		LM_DBG("route list now has %d elements\n", route_list->count);
+		
+		
+	    }
+	    if (DB_CAPABILITY(interconnectroute_dbf, DB_CAP_FETCH)) {
+		if (interconnectroute_dbf.fetch_result(interconnectroute_dbh, &route_rs, 2000/*ul_fetch_rows*/) < 0) {
+		    LM_ERR("fetching rows failed\n");
+		    interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
+		    return -1;
+		}
+	    } else {
+		break;
+	    }
+	} while (RES_ROW_N(route_rs) > 0);
+	interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
+    }
+    
+    //*route_data = new_route;
+    *ix_route_list = route_list;
+    num_rows = route_list->count;//RES_ROW_N(route_rs);
+    interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
+    LM_DBG("Returning %d rows\n", num_rows);
+    return num_rows;
+}
+
+
+int get_term_route_data(str* a_number, str* b_number, str* leg, str* sc, str* ext_trunk_id, ix_route_list_t** ix_route_list) {
+    
+    int i,n;
+    db1_res_t* route_rs;
+    db_row_t* route_row;
+    db_val_t* route_vals;
+    str query_s, incoming_trunk_id, outgoing_trunk_id;
+    route_data_t* new_route;
+    ix_route_list_t* route_list = new_route_list();
+    int num_rows;
+    
+
+    if (strlen(term_route_data_query) + a_number->len + a_number->len + b_number->len + a_number->len + leg->len + sc->len + ext_trunk_id->len > QUERY_LEN) {
+	LM_ERR("query too big\n");
+	return -1;
+    }
+    
+    snprintf(query, QUERY_LEN, term_route_data_query, a_number->len, a_number->s, a_number->len, a_number->s, b_number->len, b_number->s,
+	    b_number->len, b_number->s, sc->len, sc->s, leg->len, leg->s, ext_trunk_id->len, ext_trunk_id->s);
+    query_s.s = query;
+    query_s.len = strlen(query);
+
+    LM_DBG("get_term_route_data query is: [%s]\n", query);
+
+    if (interconnectroute_dbf.raw_query(interconnectroute_dbh, &query_s, &route_rs) != 0) {
+	LM_ERR("Unable to query DB for interconnect routes with ext trunk id [%.*s]\n", ext_trunk_id->len, ext_trunk_id->s);
+	interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
+    }
+
+    LM_DBG("Received route results [%d]\n", RES_ROW_N(route_rs));
+    if (RES_ROW_N(route_rs) <= 0) {
+	LM_DBG("No routes found for ext trunk id [%.*s]\n", ext_trunk_id->len, ext_trunk_id->s);
+	return -1;
+    } else {
+	n = 0;
+	do {
+	    n++;
+	    LM_DBG("looping through route recordset [%d]\n", n);
+	    for (i = 0; i < RES_ROW_N(route_rs); i++) {
+		route_row = RES_ROWS(route_rs) + i;
+		route_vals = ROW_VALUES(route_row);
+
+		if (!VAL_NULL(route_vals)) {
+		    incoming_trunk_id.s = (char*) VAL_STRING(route_vals);
+		    incoming_trunk_id.len = strlen(incoming_trunk_id.s);
+		    LM_DBG("incoming_trunk_id: [%.*s]\n", incoming_trunk_id.len, incoming_trunk_id.s);
+		}
+		if (!VAL_NULL(route_vals+1)) {
+		    outgoing_trunk_id.s = (char*) VAL_STRING(route_vals+1);
+		    outgoing_trunk_id.len = strlen(outgoing_trunk_id.s);
+		    LM_DBG("outgoing_trunk_id: [%.*s]\n", outgoing_trunk_id.len, outgoing_trunk_id.s);
 		}
 		}
 		
 		
-		new_route = new_route_data(&operator_key, &trunk_id, priority, &gateway_ipv4, &external_trunk_id);
+		new_route = new_route_data(&incoming_trunk_id, &outgoing_trunk_id, 0);
 		if (!new_route) {
 		if (!new_route) {
 		    LM_DBG("Could not get new route... continuing\n");
 		    LM_DBG("Could not get new route... continuing\n");
 		    continue;
 		    continue;
@@ -155,7 +254,8 @@ int get_routes(str* dst_number, route_data_t** route_data) {
 	interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
 	interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
     }
     }
     
     
-    *route_data = new_route;
+    //*route_data = new_route;
+    *ix_route_list = route_list;
     num_rows = route_list->count;//RES_ROW_N(route_rs);
     num_rows = route_list->count;//RES_ROW_N(route_rs);
     interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
     interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
     LM_DBG("Returning %d rows\n", num_rows);
     LM_DBG("Returning %d rows\n", num_rows);

+ 4 - 3
modules/interconnectroute/db.h

@@ -18,8 +18,6 @@
 #define QUERY_LEN 2048
 #define QUERY_LEN 2048
 
 
 extern str interconnectroute_db_url;
 extern str interconnectroute_db_url;
-extern str interconnectnumber_table;
-extern str interconnecttrunk_table;
 
 
 extern db1_con_t * interconnectroute_dbh;
 extern db1_con_t * interconnectroute_dbh;
 extern db_func_t interconnectroute_dbf;
 extern db_func_t interconnectroute_dbf;
@@ -28,7 +26,10 @@ void interconnectroute_db_close(void);
 int interconnectroute_db_init(void);
 int interconnectroute_db_init(void);
 int interconnectroute_db_open(void);
 int interconnectroute_db_open(void);
 
 
-int get_routes(str* dst_number, route_data_t** route_data);
+int get_orig_route_data(str* a_number, str* b_number, str* leg, str* sc, ix_route_list_t** ix_route_list);
+int get_term_route_data(str* a_number, str* b_number, str* leg, str* sc, str* ext_trunk_id, ix_route_list_t** ix_route_list);
+
+
 
 
 #endif	/* DB_H */
 #endif	/* DB_H */
 
 

+ 5 - 4
modules/interconnectroute/interconnectroute.c

@@ -8,6 +8,7 @@
 MODULE_VERSION
 MODULE_VERSION
 
 
 str interconnectroute_db_url = str_init(DEFAULT_IXDB_URL);
 str interconnectroute_db_url = str_init(DEFAULT_IXDB_URL);
+str service_code = str_init("[email protected]_1000");
 	
 	
 static int mod_init(void);
 static int mod_init(void);
 static int child_init(int);
 static int child_init(int);
@@ -16,21 +17,21 @@ static void mod_destroy(void);
 
 
 /************* Module Exports **********************************************/
 /************* Module Exports **********************************************/
 static cmd_export_t cmds[]={
 static cmd_export_t cmds[]={
-	{"ix_trunk_query",  (cmd_function)ix_trunk_query,  1, ix_trunk_query_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
+	{"ix_orig_trunk_query",  (cmd_function)ix_orig_trunk_query,  0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE },
+	{"ix_term_trunk_query",  (cmd_function)ix_term_trunk_query,  1, ix_trunk_query_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
 	{0, 0, 0, 0, 0, 0}
 	{0, 0, 0, 0, 0, 0}
 };
 };
 
 
 static param_export_t params[]= {
 static param_export_t params[]= {
     { "db_url", PARAM_STR, &interconnectroute_db_url },
     { "db_url", PARAM_STR, &interconnectroute_db_url },
-    { "numbertable", PARAM_STR, &interconnectnumber_table },
-    { "trunktable", PARAM_STR, &interconnecttrunk_table },
+    { "service_code", PARAM_STR, &service_code },
     {0,0,0}
     {0,0,0}
 };
 };
 
 
 static rpc_export_t rpc_methods[];
 static rpc_export_t rpc_methods[];
 
 
 struct module_exports exports = {
 struct module_exports exports = {
-	"carrierroute",
+	"interconnectroute",
 	DEFAULT_DLFLAGS, /* dlopen flags */
 	DEFAULT_DLFLAGS, /* dlopen flags */
 	cmds,       /* Exported functions */
 	cmds,       /* Exported functions */
 	params,     /* Export parameters */
 	params,     /* Export parameters */

+ 251 - 31
modules/interconnectroute/query.c

@@ -2,6 +2,23 @@
 #include "db.h"
 #include "db.h"
 #include "../../parser/parse_uri.h"
 #include "../../parser/parse_uri.h"
 #include "../../sr_module.h"
 #include "../../sr_module.h"
+#include "../../lib/ims/ims_getters.h"
+#include "interconnectroute.h"
+
+extern str service_code;
+
+/**We need to get the service code
+ currently we hard code this to voice service context id _ voice service id
+ This is Smile specific - think about making this more generic*/
+inline int get_service_code(str *sc) {
+    if(!service_code.s) {
+	return -1;
+    }
+    sc->s = service_code.s;
+    sc->len = service_code.len;
+    return 1;
+    
+}
 
 
 int create_response_avp_string(char* name, str* val) {
 int create_response_avp_string(char* name, str* val) {
     int rc;
     int rc;
@@ -21,10 +38,17 @@ int create_response_avp_string(char* name, str* val) {
     return 1;
     return 1;
 }
 }
 
 
-int create_avps(route_data_t* route_data) {
-    create_response_avp_string("ix_trunk_id", &route_data->trunk_id);
-    create_response_avp_string("ix_trunk_gw", &route_data->ipv4);
-    create_response_avp_string("ix_external_trunk_id", &route_data->external_trunk_id);
+int create_orig_avps(route_data_t* route_data) {
+    create_response_avp_string("ix_incoming_trunk_id", &route_data->incoming_trunk_id);
+    create_response_avp_string("ix_outgoing_trunk_id", &route_data->outgoing_trunk_id);
+    create_response_avp_string("ix_route_id", &route_data->route_id);
+    return 1;
+}
+
+int create_term_avps(route_data_t* route_data) {
+    create_response_avp_string("ix_incoming_trunk_id", &route_data->incoming_trunk_id);
+    create_response_avp_string("ix_outgoing_trunk_id", &route_data->outgoing_trunk_id);
+    return 1;
 }
 }
 
 
 int isonlydigits(str* s) {
 int isonlydigits(str* s) {
@@ -38,52 +62,248 @@ int isonlydigits(str* s) {
     return 1;
     return 1;
 }
 }
 
 
-int ix_trunk_query(struct sip_msg* msg, char* uri) {
-    str uri_number_s, number;
-    sip_uri_t* sip_uri;
-    route_data_t* route_data;
+int ix_orig_trunk_query(struct sip_msg* msg) {
+    str sc;
+    sip_uri_t calling_party_sip_uri, called_party_sip_uri;
+    ix_route_list_t* ix_route_list;
+    str called_asserted_identity = {0 , 0 },
+	asserted_identity = {0 , 0 },
+	    a_number = {0 , 0 },
+	b_number = {0 , 0 };
+    int free_called_asserted_identity = 0;
+    struct hdr_field *h=0;
+    str orig_leg = {"O", 1};
     
     
-    if (get_str_fparam(&uri_number_s, msg, (fparam_t*) uri) < 0) {
-	    LM_ERR("failed to get URI or number\n");
-	    return -1;
+    //getting asserted identity
+    if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
+	    LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
+	    if (!cscf_get_from_uri(msg, &asserted_identity)) {
+    		LM_ERR("Error assigning P-Asserted-Identity using From hdr");
+    		goto error;
+    	}
     }
     }
-    number.s = uri_number_s.s;
-    number.len = uri_number_s.len;
     
     
-    LM_DBG("IX Route: searching for URI: <%.*s>\n", number.len, number.s);
     
     
-    if (number.len < 4 || (strncmp(number.s, "sip:", 4) && strncmp(number.s, "tel:", 4))) {
-	LM_DBG("no leading tel: or sip: [%.*s] - assuming number passed in... will check => \n", number.len, number.s);
+    //getting called asserted identity
+    if ((called_asserted_identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
+	    LM_DBG("No P-Called-Identity hdr found. Using request URI for called_asserted_identity");
+	    called_asserted_identity = cscf_get_public_identity_from_requri(msg);
+	    free_called_asserted_identity = 1;
+    }
+    
+    
+    
+    LM_DBG("IX Route: Calling party [%.*s] Called party [%.*s]\n", asserted_identity.len, asserted_identity.s, called_asserted_identity.len, called_asserted_identity.s);
+    
+    /*Cleaning asserted identity*/
+    if (asserted_identity.len < 4 || (strncmp(asserted_identity.s, "sip:", 4) && strncmp(asserted_identity.s, "tel:", 4))) {
+	LM_DBG("no leading tel: or sip: [%.*s] - assuming number passed in... will check => \n", asserted_identity.len, asserted_identity.s);
     } else {
     } else {
 	//need to clean uri to extract "user" portion - which should be a number...
 	//need to clean uri to extract "user" portion - which should be a number...
-	if (parse_uri(uri_number_s.s, number.len, sip_uri) != 0) {
-	    LM_ERR("Failed to parse URI [%.*s]\n", number.len, number.s);
-	    return -1;
+	if (parse_uri(asserted_identity.s, asserted_identity.len, &calling_party_sip_uri) != 0) {
+	    LM_ERR("Failed to parse URI [%.*s]\n", asserted_identity.len, asserted_identity.s);
+	    goto error;
 	}
 	}
-	number = sip_uri->user;
+	a_number = calling_party_sip_uri.user;
+    }
+    if (a_number.len > 0 && a_number.s[0]=='+') {
+	LM_DBG("stripping off leading +\n");
+	a_number.s = a_number.s + 1;
+	a_number.len -= 1;
+    }
+    /* check this is a number? */
+    if (!isonlydigits(&a_number)) {
+	LM_WARN("not a number and not a URI... aborting\n");
+	goto error;
     }
     }
     
     
-    if (number.len > 0 && number.s[0]=='+') {
+    /*Cleaning asserted identity*/
+    if (called_asserted_identity.len < 4 || (strncmp(called_asserted_identity.s, "sip:", 4) && strncmp(called_asserted_identity.s, "tel:", 4))) {
+	LM_DBG("no leading tel: or sip: [%.*s] - assuming number passed in... will check => \n", called_asserted_identity.len, called_asserted_identity.s);
+    } else {
+	//need to clean uri to extract "user" portion - which should be a number...
+	if (parse_uri(called_asserted_identity.s, called_asserted_identity.len, &called_party_sip_uri) != 0) {
+	    LM_ERR("Failed to parse URI [%.*s]\n", called_asserted_identity.len, called_asserted_identity.s);
+	    goto error;
+	}
+	b_number = called_party_sip_uri.user;
+    }
+    if (b_number.len > 0 && b_number.s[0]=='+') {
 	LM_DBG("stripping off leading +\n");
 	LM_DBG("stripping off leading +\n");
-	number.s = number.s + 1;
-	number.len -= 1;
+	b_number.s = b_number.s + 1;
+	b_number.len -= 1;
+    }
+    /* check this is a number? */
+    if (!isonlydigits(&b_number)) {
+	LM_WARN("not a number and not a URI... aborting\n");
+	goto error;
+    }
+    
+    if(!get_service_code(&sc)){
+	LM_ERR("Could not get service code\n");
+	goto error;
+    }
+
+    LM_DBG("a_number to be searched: [%.*s], b_number to be searched: [%.*s], with service code: [%.*s] and leg [%.*s]\n", 
+	    a_number.len, a_number.s, b_number.len, b_number.s, sc.len, sc.s, orig_leg.len, orig_leg.s);
+    
+    
+    //GET ORIG ROUTE DATA 
+    //you have A number, B number, service code and direction  
+    //you want incoming trunk_id, outgoing trunk_id, route_id
+    //look up A number, B number, service code and direction in service_rate table return single highest priority entry to get from_interconnect_partner_id and to_interconnect_partner_id
+    //Join from_interconnect_partner_id with interconnect_partner table to get incoming_trunk_id
+    //Join to_interconnect_partner_id with interconnect_partner table to get outgoing_trunk_id
+    //Join outgoing_trunk_id with interconnect_trunk table to get external_trunk_id
+    //Join external_trunk_id with interconnect_route table to get route_id
+    //pass back incoming trunk_id, outgoing trunk_id, route_id
+    //S-CSCF/IPSMGW/etc. passes incoming_trunk_id, outgoing_trunk_id, service_code and direction to BM for charging and uses route-ID to route the request (use dispatcher or something similar)
+    
+    int res = get_orig_route_data(&a_number, &b_number, &orig_leg, &sc, &ix_route_list);
+    
+    if (res <= 0) {
+	goto error;
     }
     }
+    
+    LM_DBG("Received list of routes - currently we just use first in list incoming_trunk_id: [%.*s] outgoing_trunk_id [%.*s]\n", 
+	    ix_route_list->first->incoming_trunk_id.len, ix_route_list->first->incoming_trunk_id.s, ix_route_list->first->outgoing_trunk_id.len, ix_route_list->first->outgoing_trunk_id.s);
+    create_orig_avps(ix_route_list->first);
+    
+    free_route_list(ix_route_list);
 
 
+    return 1;
+    
+error:
+    if(free_called_asserted_identity) {
+	if(called_asserted_identity.s) shm_free(called_asserted_identity.s);// shm_malloc in cscf_get_public_identity_from_requri
+    }    
+
+    return -1;
+}
+
+
+/*
+ This takes in an external trunk id - gets the operator the number then gets the operator then gets the trunk details
+ */
+int ix_term_trunk_query(struct sip_msg* msg, char* ext_trunk_id) {
+    str external_trunk_id = {0, 0};
+    ix_route_list_t* ix_route_list;
+    str sc;
+    sip_uri_t calling_party_sip_uri, called_party_sip_uri;
+    str called_asserted_identity = {0 , 0 },
+	asserted_identity = {0 , 0 },
+	    a_number = {0 , 0 },
+	b_number = {0 , 0 };
+    int free_called_asserted_identity = 0;
+    struct hdr_field *h=0;
+    str term_leg = {"T", 1};
+    
+    
+    if (get_str_fparam(&external_trunk_id, msg, (fparam_t*) ext_trunk_id) < 0) {
+	    LM_ERR("failed to get external_trunk_id\n");
+	    goto error;
+    }
+    
+    //getting asserted identity
+    if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
+	    LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
+	    if (!cscf_get_from_uri(msg, &asserted_identity)) {
+    		LM_ERR("Error assigning P-Asserted-Identity using From hdr");
+    		goto error;
+    	}
+    }
+    
+    //getting called asserted identity
+    if ((called_asserted_identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
+	    LM_DBG("No P-Called-Identity hdr found. Using request URI for called_asserted_identity");
+	    called_asserted_identity = cscf_get_public_identity_from_requri(msg);
+	    free_called_asserted_identity = 1;
+    }
+    
+    LM_DBG("IX Route: Calling party [%.*s] Called party [%.*s]\n", asserted_identity.len, asserted_identity.s, called_asserted_identity.len, called_asserted_identity.s);
+    
+    /*Cleaning asserted identity*/
+    if (asserted_identity.len < 4 || (strncmp(asserted_identity.s, "sip:", 4) && strncmp(asserted_identity.s, "tel:", 4))) {
+	LM_DBG("no leading tel: or sip: [%.*s] - assuming number passed in... will check => \n", asserted_identity.len, asserted_identity.s);
+    } else {
+	//need to clean uri to extract "user" portion - which should be a number...
+	if (parse_uri(asserted_identity.s, asserted_identity.len, &calling_party_sip_uri) != 0) {
+	    LM_ERR("Failed to parse URI [%.*s]\n", asserted_identity.len, asserted_identity.s);
+	    goto error;
+	}
+	a_number = calling_party_sip_uri.user;
+    }
+    if (a_number.len > 0 && a_number.s[0]=='+') {
+	LM_DBG("stripping off leading +\n");
+	a_number.s = a_number.s + 1;
+	a_number.len -= 1;
+    }
     /* check this is a number? */
     /* check this is a number? */
-    if (!isonlydigits(&number)) {
+    if (!isonlydigits(&a_number)) {
 	LM_WARN("not a number and not a URI... aborting\n");
 	LM_WARN("not a number and not a URI... aborting\n");
-	return -1;
-    } 
+	goto error;
+    }
+    
+    /*Cleaning asserted identity*/
+    if (called_asserted_identity.len < 4 || (strncmp(called_asserted_identity.s, "sip:", 4) && strncmp(called_asserted_identity.s, "tel:", 4))) {
+	LM_DBG("no leading tel: or sip: [%.*s] - assuming number passed in... will check => \n", called_asserted_identity.len, called_asserted_identity.s);
+    } else {
+	//need to clean uri to extract "user" portion - which should be a number...
+	if (parse_uri(called_asserted_identity.s, called_asserted_identity.len, &called_party_sip_uri) != 0) {
+	    LM_ERR("Failed to parse URI [%.*s]\n", called_asserted_identity.len, called_asserted_identity.s);
+	    goto error;
+	}
+	b_number = called_party_sip_uri.user;
+    }
+    if (b_number.len > 0 && b_number.s[0]=='+') {
+	LM_DBG("stripping off leading +\n");
+	b_number.s = b_number.s + 1;
+	b_number.len -= 1;
+    }
+    /* check this is a number? */
+    if (!isonlydigits(&b_number)) {
+	LM_WARN("not a number and not a URI... aborting\n");
+	goto error;
+    }
+    
+    if(!get_service_code(&sc)){
+	LM_ERR("Could not get service code\n");
+	goto error;
+    }
 
 
-    LM_DBG("number to be searched: [%.*s]\n", number.len, number.s);
-    int res = get_routes(&number, &route_data);
+    LM_DBG("a_number to be searched: [%.*s], b_number to be searched: [%.*s], with service code: [%.*s] and leg [%.*s] and external_trunk_id [%.*s]\n", 
+	    a_number.len, a_number.s, b_number.len, b_number.s, sc.len, sc.s, term_leg.len, term_leg.s, external_trunk_id.len, external_trunk_id.s);
+    
+    
+    //GET TERM ROUTE DATA 
+    //you have A number, B number, external trunk id and direction
+    //you want incoming_trunk_id and outgoing_trunk_id
+    //pass in A number, B number, external trunk id and direction
+    //look up interconnect_route table based on external_trunk_id
+    //join with interconnect_trunk to get incoming_trunk_id
+    //join with service_rate table passing A number, B number, direction and incoming_trunk_id to get outgoing_trunk_id
+    //Pass back incoming_trunk_id and outgoing_trunk_id
+    //S-CSCF/IPSMGW/etc. passes incoming_trunk_id, outgoing_trunk_id, service_code and direction to BM for charging 
+    
+    int res = get_term_route_data(&a_number, &b_number, &term_leg, &sc, &external_trunk_id, &ix_route_list);
     
     
     if (res <= 0) {
     if (res <= 0) {
-	return -1;
+	goto error;
     }
     }
     
     
-    LM_DBG("Received route for operator key: [%.*s]\n", route_data->operator_key.len, route_data->operator_key.s);
-    create_avps(route_data);
+    LM_DBG("Received list of routes - currently we just use first in list incoming_trunk_id: [%.*s] outgoing_trunk_id [%.*s]\n", 
+	    ix_route_list->first->incoming_trunk_id.len, ix_route_list->first->incoming_trunk_id.s, ix_route_list->first->outgoing_trunk_id.len, ix_route_list->first->outgoing_trunk_id.s);
+    create_term_avps(ix_route_list->first);
+    
+    free_route_list(ix_route_list);
 
 
     return 1;
     return 1;
+    
+        
+error:
+    if(free_called_asserted_identity) {
+	if(called_asserted_identity.s) shm_free(called_asserted_identity.s);// shm_malloc in cscf_get_public_identity_from_requri
+    }    
+
+    return -1;
 }
 }

+ 2 - 2
modules/interconnectroute/query.h

@@ -10,7 +10,7 @@
 
 
 #include "../../parser/msg_parser.h"
 #include "../../parser/msg_parser.h"
 
 
-int ix_trunk_query(struct sip_msg* msg, char* uri);
-
+int ix_orig_trunk_query(struct sip_msg* msg);
+int ix_term_trunk_query(struct sip_msg* msg, char* ext_trunk_id);
 #endif	/* QUERY_H */
 #endif	/* QUERY_H */
 
 

+ 35 - 20
modules/interconnectroute/route_data.c

@@ -6,10 +6,29 @@
 /* creates a new structure to hold route data in pkg memory 
 /* creates a new structure to hold route data in pkg memory 
    NB: remember to free when done!
    NB: remember to free when done!
  */
  */
-route_data_t* new_route_data(str* operator_key, str* trunk_id, int priority, str* gw_ip, str* external_trunk_id) {
+
+int free_route_data(route_data_t* route_data) {
+    if(route_data) pkg_free(route_data);
+        return 1;
+}
+
+int free_route_list (ix_route_list_t* ix_route_list) {
+    route_data_t* tmp, *tmp1;
+    tmp = ix_route_list->first;
+    while(tmp) {
+	tmp1 = tmp->next;
+	free_route_data(tmp);
+	tmp = tmp1;
+    }
+    return 1;
+}
+
+route_data_t* new_route_data(str* incoming_trunk_id, str* outgoing_trunk_id, str* route_id) {
     struct route_data* route_data;
     struct route_data* route_data;
     char *p;
     char *p;
-    int len = sizeof(struct route_data) + operator_key->len + trunk_id->len + gw_ip->len + external_trunk_id->len;
+    int len = sizeof(struct route_data) + incoming_trunk_id->len + outgoing_trunk_id->len;
+    if(route_id) len = len + route_id->len;
+    
     route_data = (struct route_data*)pkg_malloc(len);
     route_data = (struct route_data*)pkg_malloc(len);
     if (!route_data) {
     if (!route_data) {
 	LM_ERR("no more pkg memory\n");
 	LM_ERR("no more pkg memory\n");
@@ -18,28 +37,24 @@ route_data_t* new_route_data(str* operator_key, str* trunk_id, int priority, str
     
     
     memset(route_data, 0, len);
     memset(route_data, 0, len);
     
     
-    route_data->priority = priority;
     p = (char*)(route_data + 1);
     p = (char*)(route_data + 1);
     
     
-    route_data->operator_key.s = p;
-    route_data->operator_key.len = operator_key->len;
-    memcpy(p, operator_key->s, operator_key->len);
-    p+=operator_key->len;
+    route_data->incoming_trunk_id.s = p;
+    memcpy(p, incoming_trunk_id->s, incoming_trunk_id->len);
+    route_data->incoming_trunk_id.len = incoming_trunk_id->len;
+    p+= incoming_trunk_id->len;
     
     
-    route_data->trunk_id.s = p;
-    memcpy(p, trunk_id->s, trunk_id->len);
-    route_data->trunk_id.len = trunk_id->len;
-    p+= trunk_id->len;
+    route_data->outgoing_trunk_id.s = p;
+    memcpy(p, outgoing_trunk_id->s, outgoing_trunk_id->len);
+    route_data->outgoing_trunk_id.len = outgoing_trunk_id->len;
+    p+= outgoing_trunk_id->len;
     
     
-    route_data->ipv4.s = p;
-    memcpy(p, gw_ip->s, gw_ip->len);
-    route_data->ipv4.len = gw_ip->len;
-    p+=gw_ip->len;
-    
-    route_data->external_trunk_id.s = p;
-    memcpy(p, external_trunk_id->s, external_trunk_id->len);
-    route_data->external_trunk_id.len = external_trunk_id->len;
-    p+=external_trunk_id->len;  
+    if(route_id) {
+	route_data->route_id.s = p;
+	memcpy(p, route_id->s, route_id->len);
+	route_data->route_id.len = route_id->len;
+	p+=route_id->len;
+    }
     
     
     if (p != (((char*) route_data) + len)) {
     if (p != (((char*) route_data) + len)) {
         LM_CRIT("buffer overflow\n");
         LM_CRIT("buffer overflow\n");

+ 6 - 6
modules/interconnectroute/route_data.h

@@ -11,11 +11,9 @@
 #include "../../str.h"
 #include "../../str.h"
 
 
 typedef struct route_data {
 typedef struct route_data {
-    str     operator_key;
-    str     trunk_id;
-    str     external_trunk_id;
-    str     ipv4;
-    int     priority;
+    str     incoming_trunk_id;
+    str     outgoing_trunk_id;
+    str     route_id;
     struct route_data* next;
     struct route_data* next;
     struct route_data* prev;
     struct route_data* prev;
 } route_data_t;
 } route_data_t;
@@ -26,9 +24,11 @@ typedef struct ix_route_list {
     int count;
     int count;
 } ix_route_list_t;
 } ix_route_list_t;
 
 
-route_data_t* new_route_data(str* operator_key, str* trunk_id, int priority, str* gw_ip, str* external_trunk_id);
+route_data_t* new_route_data(str* incoming_trunk_id, str* outgoing_trunk_id, str* route_id);
 ix_route_list_t* new_route_list();
 ix_route_list_t* new_route_list();
 int add_route(struct ix_route_list* list, struct route_data* route);
 int add_route(struct ix_route_list* list, struct route_data* route);
+int free_route_data(route_data_t* route_data);
+int free_route_list (ix_route_list_t* ix_route_list);
 
 
 #endif	/* ROUTE_DATA_H */
 #endif	/* ROUTE_DATA_H */