Browse code

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 authored on 13/11/2014 07:45:30
Showing 8 changed files
... ...
@@ -13,5 +13,6 @@ DEFS+=-DKAMAILIO_MOD_INTERFACE
13 13
 
14 14
 SERLIBPATH=../../lib
15 15
 SER_LIBS+=$(SERLIBPATH)/trie/trie $(SERLIBPATH)/srdb1/srdb1 $(SERLIBPATH)/kmi/kmi $(SERLIBPATH)/kcore/kcore
16
+SER_LIBS+=$(SERLIBPATH)/ims/kamailio_ims
16 17
 
17 18
 include ../../Makefile.modules
... ...
@@ -4,17 +4,40 @@
4 4
 db1_con_t * interconnectroute_dbh = NULL;
5 5
 db_func_t interconnectroute_dbf;
6 6
 
7
-static char *query_fmt = "select N.OPERATOR_KEY, T.TRUNK_ID, T.PRIORITY, T.IPV4, T.EXTERNAL_TRUNK_ID "
8
-	"from operator_number N left join operator_trunk T on N.OPERATOR_KEY=T.OPERATOR_KEY "
9
-	"where %.*s >= CAST(NUMBER_START AS UNSIGNED) and %.*s <= CAST(NUMBER_END AS UNSIGNED) ORDER BY T.PRIORITY DESC";
7
+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 "
8
+    "service_rate SR "
9
+    "join interconnect_trunk TFROM on TFROM.INTERCONNECT_PARTNER_ID = SR.FROM_INTERCONNECT_PARTNER_ID "
10
+    "join interconnect_trunk TTO on TTO.INTERCONNECT_PARTNER_ID = SR.TO_INTERCONNECT_PARTNER_ID " 
11
+    "join interconnect_route RT on TTO.EXTERNAL_ID = RT.EXTERNAL_ID "
12
+    "where "
13
+    "%.*s >= SR.FROM_START "
14
+    "and %.*s <= SR.FROM_END "
15
+    "and %.*s >= SR.TO_START "
16
+    "and %.*s <= SR.TO_END "
17
+    "and SR.SERVICE_CODE = '%.*s' "
18
+    "and SR.LEG = '%.*s' "
19
+    "order by SR.PRIORITY DESC, RT.PRIORITY DESC LIMIT 1";
20
+
21
+static char *term_route_data_query = "select TFROM.INTERNAL_ID as FROM_TRUNK_ID, TTO.INTERNAL_ID as TO_TRUNK_ID from "
22
+    "service_rate SR "
23
+    "join interconnect_trunk TFROM on TFROM.INTERCONNECT_PARTNER_ID = SR.FROM_INTERCONNECT_PARTNER_ID "
24
+    "join interconnect_trunk TTO on TTO.INTERCONNECT_PARTNER_ID = SR.TO_INTERCONNECT_PARTNER_ID "
25
+    "where "
26
+    "%.*s >= SR.TO_START "
27
+    "and %.*s <= SR.TO_END "
28
+    "and %.*s >= SR.FROM_START "
29
+    "and %.*s <= SR.FROM_END "
30
+    "and SR.SERVICE_CODE = '%.*s' "
31
+    "and SR.LEG = '%.*s' "
32
+    "and TFROM.EXTERNAL_ID = '%.*s';";
33
+
10 34
 static char query[QUERY_LEN];
11 35
 
12
-str interconnectnumber_table = str_init("operator_number");
13 36
 
14
-/* table version */
15
-const unsigned int interconnectroute_version = 1;
37
+str interconnect_trunk_table = str_init("interconnect_trunk");
38
+str interconnect_route_table = str_init("interconnect_route");
39
+str service_rate_table = str_init("service_rate");
16 40
 
17
-str interconnecttrunk_table = str_init("operator_trunk");
18 41
 
19 42
 /*
20 43
  * Closes the DB connection.
... ...
@@ -40,13 +63,6 @@ int interconnectroute_db_init(void) {
40 63
 	LM_ERR("can't connect to database using [%.*s]\n", interconnectroute_db_url.len, interconnectroute_db_url.s);
41 64
 	return -1;
42 65
     }
43
-    if (
44
-	    (db_check_table_version(&interconnectroute_dbf, interconnectroute_dbh, &interconnectnumber_table, interconnectroute_version) < 0) ||
45
-	    (db_check_table_version(&interconnectroute_dbf, interconnectroute_dbh, &interconnecttrunk_table, interconnectroute_version) < 0)) {
46
-	LM_ERR("during table version check.\n");
47
-	interconnectroute_db_close();
48
-	return -1;
49
-    }
50 66
     interconnectroute_db_close();
51 67
     return 0;
52 68
 }
... ...
@@ -63,35 +79,37 @@ int interconnectroute_db_open(void) {
63 79
     return 0;
64 80
 }
65 81
 
66
-int get_routes(str* dst_number, route_data_t** route_data) {
67
-    int i,n, priority;
82
+
83
+int get_orig_route_data(str* a_number, str* b_number, str* leg, str* sc, ix_route_list_t** ix_route_list) {
84
+    int i,n;
68 85
     db1_res_t* route_rs;
69 86
     db_row_t* route_row;
70 87
     db_val_t* route_vals;
71
-    str query_s, operator_key, trunk_id, external_trunk_id, gateway_ipv4;
88
+    str query_s, incoming_trunk_id, outgoing_trunk_id, route_id;
72 89
     route_data_t* new_route;
73 90
     ix_route_list_t* route_list = new_route_list();
74 91
     int num_rows;
75 92
     
76 93
 
77
-    if (strlen(query_fmt) + dst_number->len > QUERY_LEN) {
94
+    if (strlen(orig_route_data_query) + a_number->len + a_number->len + b_number->len + b_number->len + leg->len + sc->len > QUERY_LEN) {
78 95
 	LM_ERR("query too big\n");
79 96
 	return -1;
80 97
     }
81
-    snprintf(query, QUERY_LEN, query_fmt, dst_number->len, dst_number->s, dst_number->len, dst_number->s);
98
+    
99
+    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,
100
+	    b_number->len, b_number->s, sc->len, sc->s, leg->len, leg->s);
82 101
     query_s.s = query;
83 102
     query_s.len = strlen(query);
84 103
 
85
-    LM_DBG("QUERY IS: [%s]\n", query);
86
-
104
+    LM_DBG("get_orig_route_data query is: [%s]\n", query);
87 105
     if (interconnectroute_dbf.raw_query(interconnectroute_dbh, &query_s, &route_rs) != 0) {
88
-	LM_ERR("Unable to query DB for interconnect routes with number [%.*s]\n", dst_number->len, dst_number->s);
106
+	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);
89 107
 	interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
90 108
     }
91 109
 
92 110
     LM_DBG("Received route results [%d]\n", RES_ROW_N(route_rs));
93 111
     if (RES_ROW_N(route_rs) <= 0) {
94
-	LM_DBG("No routes found for number [%.*s]\n", dst_number->len, dst_number->s);
112
+	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);
95 113
 	return -1;
96 114
     } else {
97 115
 	n = 0;
... ...
@@ -103,31 +121,112 @@ int get_routes(str* dst_number, route_data_t** route_data) {
103 121
 		route_vals = ROW_VALUES(route_row);
104 122
 
105 123
 		if (!VAL_NULL(route_vals)) {
106
-		    operator_key.s = (char*) VAL_STRING(route_vals);
107
-		    operator_key.len = strlen(operator_key.s);
108
-		    LM_DBG("Received route for operator key: [%.*s]\n", operator_key.len, operator_key.s);
124
+		    incoming_trunk_id.s = (char*) VAL_STRING(route_vals);
125
+		    incoming_trunk_id.len = strlen(incoming_trunk_id.s);
126
+		    LM_DBG("incoming_trunk_id: [%.*s]\n", incoming_trunk_id.len, incoming_trunk_id.s);
109 127
 		}
110 128
 		if (!VAL_NULL(route_vals+1)) {
111
-		    trunk_id.s = (char*) VAL_STRING(route_vals+1);
112
-		    trunk_id.len = strlen(trunk_id.s);
113
-		    LM_DBG("Trunk is: [%.*s]\n", trunk_id.len, trunk_id.s);
129
+		    outgoing_trunk_id.s = (char*) VAL_STRING(route_vals+1);
130
+		    outgoing_trunk_id.len = strlen(outgoing_trunk_id.s);
131
+		    LM_DBG("outgoing_trunk_id: [%.*s]\n", outgoing_trunk_id.len, outgoing_trunk_id.s);
114 132
 		}
115 133
 		if (!VAL_NULL(route_vals+2)) {
116
-		    priority = VAL_INT(route_vals+2);
117
-		    LM_DBG("Priority is: [%d]\n", priority);
134
+		    route_id.s = (char*) VAL_STRING(route_vals+2);
135
+		    route_id.len = strlen(route_id.s);
136
+		    LM_DBG("route_id: [%.*s]\n", route_id.len, route_id.s);
137
+		}
138
+		
139
+		new_route = new_route_data(&incoming_trunk_id, &outgoing_trunk_id, &route_id);
140
+		if (!new_route) {
141
+		    LM_DBG("Could not get new route... continuing\n");
142
+		    continue;
118 143
 		}
119
-		if (!VAL_NULL(route_vals+3)) {
120
-		    gateway_ipv4.s = (char*) VAL_STRING(route_vals+3);
121
-		    gateway_ipv4.len = strlen(gateway_ipv4.s);
122
-		    LM_DBG("Gateway IP for trunk to this operator is: [%.*s]\n", gateway_ipv4.len, gateway_ipv4.s);
144
+		
145
+		if (!add_route(route_list, new_route)) {
146
+		    LM_DBG("unable to add route.....\n");
147
+		    continue;
123 148
 		}
124
-		if (!VAL_NULL(route_vals+4)) {
125
-		    external_trunk_id.s = (char*) VAL_STRING(route_vals+4);
126
-		    external_trunk_id.len = strlen(external_trunk_id.s);
127
-		    LM_DBG("External trunk ID: [%.*s]\n", external_trunk_id.len, external_trunk_id.s);
149
+		
150
+		LM_DBG("route list now has %d elements\n", route_list->count);
151
+		
152
+		
153
+	    }
154
+	    if (DB_CAPABILITY(interconnectroute_dbf, DB_CAP_FETCH)) {
155
+		if (interconnectroute_dbf.fetch_result(interconnectroute_dbh, &route_rs, 2000/*ul_fetch_rows*/) < 0) {
156
+		    LM_ERR("fetching rows failed\n");
157
+		    interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
158
+		    return -1;
159
+		}
160
+	    } else {
161
+		break;
162
+	    }
163
+	} while (RES_ROW_N(route_rs) > 0);
164
+	interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
165
+    }
166
+    
167
+    //*route_data = new_route;
168
+    *ix_route_list = route_list;
169
+    num_rows = route_list->count;//RES_ROW_N(route_rs);
170
+    interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
171
+    LM_DBG("Returning %d rows\n", num_rows);
172
+    return num_rows;
173
+}
174
+
175
+
176
+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) {
177
+    
178
+    int i,n;
179
+    db1_res_t* route_rs;
180
+    db_row_t* route_row;
181
+    db_val_t* route_vals;
182
+    str query_s, incoming_trunk_id, outgoing_trunk_id;
183
+    route_data_t* new_route;
184
+    ix_route_list_t* route_list = new_route_list();
185
+    int num_rows;
186
+    
187
+
188
+    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) {
189
+	LM_ERR("query too big\n");
190
+	return -1;
191
+    }
192
+    
193
+    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,
194
+	    b_number->len, b_number->s, sc->len, sc->s, leg->len, leg->s, ext_trunk_id->len, ext_trunk_id->s);
195
+    query_s.s = query;
196
+    query_s.len = strlen(query);
197
+
198
+    LM_DBG("get_term_route_data query is: [%s]\n", query);
199
+
200
+    if (interconnectroute_dbf.raw_query(interconnectroute_dbh, &query_s, &route_rs) != 0) {
201
+	LM_ERR("Unable to query DB for interconnect routes with ext trunk id [%.*s]\n", ext_trunk_id->len, ext_trunk_id->s);
202
+	interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
203
+    }
204
+
205
+    LM_DBG("Received route results [%d]\n", RES_ROW_N(route_rs));
206
+    if (RES_ROW_N(route_rs) <= 0) {
207
+	LM_DBG("No routes found for ext trunk id [%.*s]\n", ext_trunk_id->len, ext_trunk_id->s);
208
+	return -1;
209
+    } else {
210
+	n = 0;
211
+	do {
212
+	    n++;
213
+	    LM_DBG("looping through route recordset [%d]\n", n);
214
+	    for (i = 0; i < RES_ROW_N(route_rs); i++) {
215
+		route_row = RES_ROWS(route_rs) + i;
216
+		route_vals = ROW_VALUES(route_row);
217
+
218
+		if (!VAL_NULL(route_vals)) {
219
+		    incoming_trunk_id.s = (char*) VAL_STRING(route_vals);
220
+		    incoming_trunk_id.len = strlen(incoming_trunk_id.s);
221
+		    LM_DBG("incoming_trunk_id: [%.*s]\n", incoming_trunk_id.len, incoming_trunk_id.s);
222
+		}
223
+		if (!VAL_NULL(route_vals+1)) {
224
+		    outgoing_trunk_id.s = (char*) VAL_STRING(route_vals+1);
225
+		    outgoing_trunk_id.len = strlen(outgoing_trunk_id.s);
226
+		    LM_DBG("outgoing_trunk_id: [%.*s]\n", outgoing_trunk_id.len, outgoing_trunk_id.s);
128 227
 		}
129 228
 		
130
-		new_route = new_route_data(&operator_key, &trunk_id, priority, &gateway_ipv4, &external_trunk_id);
229
+		new_route = new_route_data(&incoming_trunk_id, &outgoing_trunk_id, 0);
131 230
 		if (!new_route) {
132 231
 		    LM_DBG("Could not get new route... continuing\n");
133 232
 		    continue;
... ...
@@ -155,7 +254,8 @@ int get_routes(str* dst_number, route_data_t** route_data) {
155 254
 	interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
156 255
     }
157 256
     
158
-    *route_data = new_route;
257
+    //*route_data = new_route;
258
+    *ix_route_list = route_list;
159 259
     num_rows = route_list->count;//RES_ROW_N(route_rs);
160 260
     interconnectroute_dbf.free_result(interconnectroute_dbh, route_rs);
161 261
     LM_DBG("Returning %d rows\n", num_rows);
... ...
@@ -18,8 +18,6 @@
18 18
 #define QUERY_LEN 2048
19 19
 
20 20
 extern str interconnectroute_db_url;
21
-extern str interconnectnumber_table;
22
-extern str interconnecttrunk_table;
23 21
 
24 22
 extern db1_con_t * interconnectroute_dbh;
25 23
 extern db_func_t interconnectroute_dbf;
... ...
@@ -28,7 +26,10 @@ void interconnectroute_db_close(void);
28 26
 int interconnectroute_db_init(void);
29 27
 int interconnectroute_db_open(void);
30 28
 
31
-int get_routes(str* dst_number, route_data_t** route_data);
29
+int get_orig_route_data(str* a_number, str* b_number, str* leg, str* sc, ix_route_list_t** ix_route_list);
30
+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);
31
+
32
+
32 33
 
33 34
 #endif	/* DB_H */
34 35
 
... ...
@@ -8,6 +8,7 @@
8 8
 MODULE_VERSION
9 9
 
10 10
 str interconnectroute_db_url = str_init(DEFAULT_IXDB_URL);
11
+str service_code = str_init("ext.01.001.8.32260@3gpp.org_1000");
11 12
 	
12 13
 static int mod_init(void);
13 14
 static int child_init(int);
... ...
@@ -16,21 +17,21 @@ static void mod_destroy(void);
16 17
 
17 18
 /************* Module Exports **********************************************/
18 19
 static cmd_export_t cmds[]={
19
-	{"ix_trunk_query",  (cmd_function)ix_trunk_query,  1, ix_trunk_query_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
20
+	{"ix_orig_trunk_query",  (cmd_function)ix_orig_trunk_query,  0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE },
21
+	{"ix_term_trunk_query",  (cmd_function)ix_term_trunk_query,  1, ix_trunk_query_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
20 22
 	{0, 0, 0, 0, 0, 0}
21 23
 };
22 24
 
23 25
 static param_export_t params[]= {
24 26
     { "db_url", PARAM_STR, &interconnectroute_db_url },
25
-    { "numbertable", PARAM_STR, &interconnectnumber_table },
26
-    { "trunktable", PARAM_STR, &interconnecttrunk_table },
27
+    { "service_code", PARAM_STR, &service_code },
27 28
     {0,0,0}
28 29
 };
29 30
 
30 31
 static rpc_export_t rpc_methods[];
31 32
 
32 33
 struct module_exports exports = {
33
-	"carrierroute",
34
+	"interconnectroute",
34 35
 	DEFAULT_DLFLAGS, /* dlopen flags */
35 36
 	cmds,       /* Exported functions */
36 37
 	params,     /* Export parameters */
... ...
@@ -2,6 +2,23 @@
2 2
 #include "db.h"
3 3
 #include "../../parser/parse_uri.h"
4 4
 #include "../../sr_module.h"
5
+#include "../../lib/ims/ims_getters.h"
6
+#include "interconnectroute.h"
7
+
8
+extern str service_code;
9
+
10
+/**We need to get the service code
11
+ currently we hard code this to voice service context id _ voice service id
12
+ This is Smile specific - think about making this more generic*/
13
+inline int get_service_code(str *sc) {
14
+    if(!service_code.s) {
15
+	return -1;
16
+    }
17
+    sc->s = service_code.s;
18
+    sc->len = service_code.len;
19
+    return 1;
20
+    
21
+}
5 22
 
6 23
 int create_response_avp_string(char* name, str* val) {
7 24
     int rc;
... ...
@@ -21,10 +38,17 @@ int create_response_avp_string(char* name, str* val) {
21 38
     return 1;
22 39
 }
23 40
 
24
-int create_avps(route_data_t* route_data) {
25
-    create_response_avp_string("ix_trunk_id", &route_data->trunk_id);
26
-    create_response_avp_string("ix_trunk_gw", &route_data->ipv4);
27
-    create_response_avp_string("ix_external_trunk_id", &route_data->external_trunk_id);
41
+int create_orig_avps(route_data_t* route_data) {
42
+    create_response_avp_string("ix_incoming_trunk_id", &route_data->incoming_trunk_id);
43
+    create_response_avp_string("ix_outgoing_trunk_id", &route_data->outgoing_trunk_id);
44
+    create_response_avp_string("ix_route_id", &route_data->route_id);
45
+    return 1;
46
+}
47
+
48
+int create_term_avps(route_data_t* route_data) {
49
+    create_response_avp_string("ix_incoming_trunk_id", &route_data->incoming_trunk_id);
50
+    create_response_avp_string("ix_outgoing_trunk_id", &route_data->outgoing_trunk_id);
51
+    return 1;
28 52
 }
29 53
 
30 54
 int isonlydigits(str* s) {
... ...
@@ -38,52 +62,248 @@ int isonlydigits(str* s) {
38 62
     return 1;
39 63
 }
40 64
 
41
-int ix_trunk_query(struct sip_msg* msg, char* uri) {
42
-    str uri_number_s, number;
43
-    sip_uri_t* sip_uri;
44
-    route_data_t* route_data;
65
+int ix_orig_trunk_query(struct sip_msg* msg) {
66
+    str sc;
67
+    sip_uri_t calling_party_sip_uri, called_party_sip_uri;
68
+    ix_route_list_t* ix_route_list;
69
+    str called_asserted_identity = {0 , 0 },
70
+	asserted_identity = {0 , 0 },
71
+	    a_number = {0 , 0 },
72
+	b_number = {0 , 0 };
73
+    int free_called_asserted_identity = 0;
74
+    struct hdr_field *h=0;
75
+    str orig_leg = {"O", 1};
45 76
     
46
-    if (get_str_fparam(&uri_number_s, msg, (fparam_t*) uri) < 0) {
47
-	    LM_ERR("failed to get URI or number\n");
48
-	    return -1;
77
+    //getting asserted identity
78
+    if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
79
+	    LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
80
+	    if (!cscf_get_from_uri(msg, &asserted_identity)) {
81
+    		LM_ERR("Error assigning P-Asserted-Identity using From hdr");
82
+    		goto error;
83
+    	}
49 84
     }
50
-    number.s = uri_number_s.s;
51
-    number.len = uri_number_s.len;
52 85
     
53
-    LM_DBG("IX Route: searching for URI: <%.*s>\n", number.len, number.s);
54 86
     
55
-    if (number.len < 4 || (strncmp(number.s, "sip:", 4) && strncmp(number.s, "tel:", 4))) {
56
-	LM_DBG("no leading tel: or sip: [%.*s] - assuming number passed in... will check => \n", number.len, number.s);
87
+    //getting called asserted identity
88
+    if ((called_asserted_identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
89
+	    LM_DBG("No P-Called-Identity hdr found. Using request URI for called_asserted_identity");
90
+	    called_asserted_identity = cscf_get_public_identity_from_requri(msg);
91
+	    free_called_asserted_identity = 1;
92
+    }
93
+    
94
+    
95
+    
96
+    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);
97
+    
98
+    /*Cleaning asserted identity*/
99
+    if (asserted_identity.len < 4 || (strncmp(asserted_identity.s, "sip:", 4) && strncmp(asserted_identity.s, "tel:", 4))) {
100
+	LM_DBG("no leading tel: or sip: [%.*s] - assuming number passed in... will check => \n", asserted_identity.len, asserted_identity.s);
57 101
     } else {
58 102
 	//need to clean uri to extract "user" portion - which should be a number...
59
-	if (parse_uri(uri_number_s.s, number.len, sip_uri) != 0) {
60
-	    LM_ERR("Failed to parse URI [%.*s]\n", number.len, number.s);
61
-	    return -1;
103
+	if (parse_uri(asserted_identity.s, asserted_identity.len, &calling_party_sip_uri) != 0) {
104
+	    LM_ERR("Failed to parse URI [%.*s]\n", asserted_identity.len, asserted_identity.s);
105
+	    goto error;
62 106
 	}
63
-	number = sip_uri->user;
107
+	a_number = calling_party_sip_uri.user;
108
+    }
109
+    if (a_number.len > 0 && a_number.s[0]=='+') {
110
+	LM_DBG("stripping off leading +\n");
111
+	a_number.s = a_number.s + 1;
112
+	a_number.len -= 1;
113
+    }
114
+    /* check this is a number? */
115
+    if (!isonlydigits(&a_number)) {
116
+	LM_WARN("not a number and not a URI... aborting\n");
117
+	goto error;
64 118
     }
65 119
     
66
-    if (number.len > 0 && number.s[0]=='+') {
120
+    /*Cleaning asserted identity*/
121
+    if (called_asserted_identity.len < 4 || (strncmp(called_asserted_identity.s, "sip:", 4) && strncmp(called_asserted_identity.s, "tel:", 4))) {
122
+	LM_DBG("no leading tel: or sip: [%.*s] - assuming number passed in... will check => \n", called_asserted_identity.len, called_asserted_identity.s);
123
+    } else {
124
+	//need to clean uri to extract "user" portion - which should be a number...
125
+	if (parse_uri(called_asserted_identity.s, called_asserted_identity.len, &called_party_sip_uri) != 0) {
126
+	    LM_ERR("Failed to parse URI [%.*s]\n", called_asserted_identity.len, called_asserted_identity.s);
127
+	    goto error;
128
+	}
129
+	b_number = called_party_sip_uri.user;
130
+    }
131
+    if (b_number.len > 0 && b_number.s[0]=='+') {
67 132
 	LM_DBG("stripping off leading +\n");
68
-	number.s = number.s + 1;
69
-	number.len -= 1;
133
+	b_number.s = b_number.s + 1;
134
+	b_number.len -= 1;
135
+    }
136
+    /* check this is a number? */
137
+    if (!isonlydigits(&b_number)) {
138
+	LM_WARN("not a number and not a URI... aborting\n");
139
+	goto error;
140
+    }
141
+    
142
+    if(!get_service_code(&sc)){
143
+	LM_ERR("Could not get service code\n");
144
+	goto error;
145
+    }
146
+
147
+    LM_DBG("a_number to be searched: [%.*s], b_number to be searched: [%.*s], with service code: [%.*s] and leg [%.*s]\n", 
148
+	    a_number.len, a_number.s, b_number.len, b_number.s, sc.len, sc.s, orig_leg.len, orig_leg.s);
149
+    
150
+    
151
+    //GET ORIG ROUTE DATA 
152
+    //you have A number, B number, service code and direction  
153
+    //you want incoming trunk_id, outgoing trunk_id, route_id
154
+    //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
155
+    //Join from_interconnect_partner_id with interconnect_partner table to get incoming_trunk_id
156
+    //Join to_interconnect_partner_id with interconnect_partner table to get outgoing_trunk_id
157
+    //Join outgoing_trunk_id with interconnect_trunk table to get external_trunk_id
158
+    //Join external_trunk_id with interconnect_route table to get route_id
159
+    //pass back incoming trunk_id, outgoing trunk_id, route_id
160
+    //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)
161
+    
162
+    int res = get_orig_route_data(&a_number, &b_number, &orig_leg, &sc, &ix_route_list);
163
+    
164
+    if (res <= 0) {
165
+	goto error;
70 166
     }
167
+    
168
+    LM_DBG("Received list of routes - currently we just use first in list incoming_trunk_id: [%.*s] outgoing_trunk_id [%.*s]\n", 
169
+	    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);
170
+    create_orig_avps(ix_route_list->first);
171
+    
172
+    free_route_list(ix_route_list);
71 173
 
174
+    return 1;
175
+    
176
+error:
177
+    if(free_called_asserted_identity) {
178
+	if(called_asserted_identity.s) shm_free(called_asserted_identity.s);// shm_malloc in cscf_get_public_identity_from_requri
179
+    }    
180
+
181
+    return -1;
182
+}
183
+
184
+
185
+/*
186
+ This takes in an external trunk id - gets the operator the number then gets the operator then gets the trunk details
187
+ */
188
+int ix_term_trunk_query(struct sip_msg* msg, char* ext_trunk_id) {
189
+    str external_trunk_id = {0, 0};
190
+    ix_route_list_t* ix_route_list;
191
+    str sc;
192
+    sip_uri_t calling_party_sip_uri, called_party_sip_uri;
193
+    str called_asserted_identity = {0 , 0 },
194
+	asserted_identity = {0 , 0 },
195
+	    a_number = {0 , 0 },
196
+	b_number = {0 , 0 };
197
+    int free_called_asserted_identity = 0;
198
+    struct hdr_field *h=0;
199
+    str term_leg = {"T", 1};
200
+    
201
+    
202
+    if (get_str_fparam(&external_trunk_id, msg, (fparam_t*) ext_trunk_id) < 0) {
203
+	    LM_ERR("failed to get external_trunk_id\n");
204
+	    goto error;
205
+    }
206
+    
207
+    //getting asserted identity
208
+    if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
209
+	    LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
210
+	    if (!cscf_get_from_uri(msg, &asserted_identity)) {
211
+    		LM_ERR("Error assigning P-Asserted-Identity using From hdr");
212
+    		goto error;
213
+    	}
214
+    }
215
+    
216
+    //getting called asserted identity
217
+    if ((called_asserted_identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
218
+	    LM_DBG("No P-Called-Identity hdr found. Using request URI for called_asserted_identity");
219
+	    called_asserted_identity = cscf_get_public_identity_from_requri(msg);
220
+	    free_called_asserted_identity = 1;
221
+    }
222
+    
223
+    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);
224
+    
225
+    /*Cleaning asserted identity*/
226
+    if (asserted_identity.len < 4 || (strncmp(asserted_identity.s, "sip:", 4) && strncmp(asserted_identity.s, "tel:", 4))) {
227
+	LM_DBG("no leading tel: or sip: [%.*s] - assuming number passed in... will check => \n", asserted_identity.len, asserted_identity.s);
228
+    } else {
229
+	//need to clean uri to extract "user" portion - which should be a number...
230
+	if (parse_uri(asserted_identity.s, asserted_identity.len, &calling_party_sip_uri) != 0) {
231
+	    LM_ERR("Failed to parse URI [%.*s]\n", asserted_identity.len, asserted_identity.s);
232
+	    goto error;
233
+	}
234
+	a_number = calling_party_sip_uri.user;
235
+    }
236
+    if (a_number.len > 0 && a_number.s[0]=='+') {
237
+	LM_DBG("stripping off leading +\n");
238
+	a_number.s = a_number.s + 1;
239
+	a_number.len -= 1;
240
+    }
72 241
     /* check this is a number? */
73
-    if (!isonlydigits(&number)) {
242
+    if (!isonlydigits(&a_number)) {
74 243
 	LM_WARN("not a number and not a URI... aborting\n");
75
-	return -1;
76
-    } 
244
+	goto error;
245
+    }
246
+    
247
+    /*Cleaning asserted identity*/
248
+    if (called_asserted_identity.len < 4 || (strncmp(called_asserted_identity.s, "sip:", 4) && strncmp(called_asserted_identity.s, "tel:", 4))) {
249
+	LM_DBG("no leading tel: or sip: [%.*s] - assuming number passed in... will check => \n", called_asserted_identity.len, called_asserted_identity.s);
250
+    } else {
251
+	//need to clean uri to extract "user" portion - which should be a number...
252
+	if (parse_uri(called_asserted_identity.s, called_asserted_identity.len, &called_party_sip_uri) != 0) {
253
+	    LM_ERR("Failed to parse URI [%.*s]\n", called_asserted_identity.len, called_asserted_identity.s);
254
+	    goto error;
255
+	}
256
+	b_number = called_party_sip_uri.user;
257
+    }
258
+    if (b_number.len > 0 && b_number.s[0]=='+') {
259
+	LM_DBG("stripping off leading +\n");
260
+	b_number.s = b_number.s + 1;
261
+	b_number.len -= 1;
262
+    }
263
+    /* check this is a number? */
264
+    if (!isonlydigits(&b_number)) {
265
+	LM_WARN("not a number and not a URI... aborting\n");
266
+	goto error;
267
+    }
268
+    
269
+    if(!get_service_code(&sc)){
270
+	LM_ERR("Could not get service code\n");
271
+	goto error;
272
+    }
77 273
 
78
-    LM_DBG("number to be searched: [%.*s]\n", number.len, number.s);
79
-    int res = get_routes(&number, &route_data);
274
+    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", 
275
+	    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);
276
+    
277
+    
278
+    //GET TERM ROUTE DATA 
279
+    //you have A number, B number, external trunk id and direction
280
+    //you want incoming_trunk_id and outgoing_trunk_id
281
+    //pass in A number, B number, external trunk id and direction
282
+    //look up interconnect_route table based on external_trunk_id
283
+    //join with interconnect_trunk to get incoming_trunk_id
284
+    //join with service_rate table passing A number, B number, direction and incoming_trunk_id to get outgoing_trunk_id
285
+    //Pass back incoming_trunk_id and outgoing_trunk_id
286
+    //S-CSCF/IPSMGW/etc. passes incoming_trunk_id, outgoing_trunk_id, service_code and direction to BM for charging 
287
+    
288
+    int res = get_term_route_data(&a_number, &b_number, &term_leg, &sc, &external_trunk_id, &ix_route_list);
80 289
     
81 290
     if (res <= 0) {
82
-	return -1;
291
+	goto error;
83 292
     }
84 293
     
85
-    LM_DBG("Received route for operator key: [%.*s]\n", route_data->operator_key.len, route_data->operator_key.s);
86
-    create_avps(route_data);
294
+    LM_DBG("Received list of routes - currently we just use first in list incoming_trunk_id: [%.*s] outgoing_trunk_id [%.*s]\n", 
295
+	    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);
296
+    create_term_avps(ix_route_list->first);
297
+    
298
+    free_route_list(ix_route_list);
87 299
 
88 300
     return 1;
301
+    
302
+        
303
+error:
304
+    if(free_called_asserted_identity) {
305
+	if(called_asserted_identity.s) shm_free(called_asserted_identity.s);// shm_malloc in cscf_get_public_identity_from_requri
306
+    }    
307
+
308
+    return -1;
89 309
 }
90 310
\ No newline at end of file
... ...
@@ -10,7 +10,7 @@
10 10
 
11 11
 #include "../../parser/msg_parser.h"
12 12
 
13
-int ix_trunk_query(struct sip_msg* msg, char* uri);
14
-
13
+int ix_orig_trunk_query(struct sip_msg* msg);
14
+int ix_term_trunk_query(struct sip_msg* msg, char* ext_trunk_id);
15 15
 #endif	/* QUERY_H */
16 16
 
... ...
@@ -6,10 +6,29 @@
6 6
 /* creates a new structure to hold route data in pkg memory 
7 7
    NB: remember to free when done!
8 8
  */
9
-route_data_t* new_route_data(str* operator_key, str* trunk_id, int priority, str* gw_ip, str* external_trunk_id) {
9
+
10
+int free_route_data(route_data_t* route_data) {
11
+    if(route_data) pkg_free(route_data);
12
+        return 1;
13
+}
14
+
15
+int free_route_list (ix_route_list_t* ix_route_list) {
16
+    route_data_t* tmp, *tmp1;
17
+    tmp = ix_route_list->first;
18
+    while(tmp) {
19
+	tmp1 = tmp->next;
20
+	free_route_data(tmp);
21
+	tmp = tmp1;
22
+    }
23
+    return 1;
24
+}
25
+
26
+route_data_t* new_route_data(str* incoming_trunk_id, str* outgoing_trunk_id, str* route_id) {
10 27
     struct route_data* route_data;
11 28
     char *p;
12
-    int len = sizeof(struct route_data) + operator_key->len + trunk_id->len + gw_ip->len + external_trunk_id->len;
29
+    int len = sizeof(struct route_data) + incoming_trunk_id->len + outgoing_trunk_id->len;
30
+    if(route_id) len = len + route_id->len;
31
+    
13 32
     route_data = (struct route_data*)pkg_malloc(len);
14 33
     if (!route_data) {
15 34
 	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
18 37
     
19 38
     memset(route_data, 0, len);
20 39
     
21
-    route_data->priority = priority;
22 40
     p = (char*)(route_data + 1);
23 41
     
24
-    route_data->operator_key.s = p;
25
-    route_data->operator_key.len = operator_key->len;
26
-    memcpy(p, operator_key->s, operator_key->len);
27
-    p+=operator_key->len;
42
+    route_data->incoming_trunk_id.s = p;
43
+    memcpy(p, incoming_trunk_id->s, incoming_trunk_id->len);
44
+    route_data->incoming_trunk_id.len = incoming_trunk_id->len;
45
+    p+= incoming_trunk_id->len;
28 46
     
29
-    route_data->trunk_id.s = p;
30
-    memcpy(p, trunk_id->s, trunk_id->len);
31
-    route_data->trunk_id.len = trunk_id->len;
32
-    p+= trunk_id->len;
47
+    route_data->outgoing_trunk_id.s = p;
48
+    memcpy(p, outgoing_trunk_id->s, outgoing_trunk_id->len);
49
+    route_data->outgoing_trunk_id.len = outgoing_trunk_id->len;
50
+    p+= outgoing_trunk_id->len;
33 51
     
34
-    route_data->ipv4.s = p;
35
-    memcpy(p, gw_ip->s, gw_ip->len);
36
-    route_data->ipv4.len = gw_ip->len;
37
-    p+=gw_ip->len;
38
-    
39
-    route_data->external_trunk_id.s = p;
40
-    memcpy(p, external_trunk_id->s, external_trunk_id->len);
41
-    route_data->external_trunk_id.len = external_trunk_id->len;
42
-    p+=external_trunk_id->len;  
52
+    if(route_id) {
53
+	route_data->route_id.s = p;
54
+	memcpy(p, route_id->s, route_id->len);
55
+	route_data->route_id.len = route_id->len;
56
+	p+=route_id->len;
57
+    }
43 58
     
44 59
     if (p != (((char*) route_data) + len)) {
45 60
         LM_CRIT("buffer overflow\n");
... ...
@@ -11,11 +11,9 @@
11 11
 #include "../../str.h"
12 12
 
13 13
 typedef struct route_data {
14
-    str     operator_key;
15
-    str     trunk_id;
16
-    str     external_trunk_id;
17
-    str     ipv4;
18
-    int     priority;
14
+    str     incoming_trunk_id;
15
+    str     outgoing_trunk_id;
16
+    str     route_id;
19 17
     struct route_data* next;
20 18
     struct route_data* prev;
21 19
 } route_data_t;
... ...
@@ -26,9 +24,11 @@ typedef struct ix_route_list {
26 24
     int count;
27 25
 } ix_route_list_t;
28 26
 
29
-route_data_t* new_route_data(str* operator_key, str* trunk_id, int priority, str* gw_ip, str* external_trunk_id);
27
+route_data_t* new_route_data(str* incoming_trunk_id, str* outgoing_trunk_id, str* route_id);
30 28
 ix_route_list_t* new_route_list();
31 29
 int add_route(struct ix_route_list* list, struct route_data* route);
30
+int free_route_data(route_data_t* route_data);
31
+int free_route_list (ix_route_list_t* ix_route_list);
32 32
 
33 33
 #endif	/* ROUTE_DATA_H */
34 34