|
@@ -33,6 +33,9 @@ char* ro_service_context_id_ext_s = "ext";
|
|
|
char* ro_service_context_id_mnc_s = "01";
|
|
|
char* ro_service_context_id_mcc_s = "001";
|
|
|
char* ro_service_context_id_release_s = "8";
|
|
|
+int termination_code = 0;
|
|
|
+int vendor_specific_id = 10;
|
|
|
+int vendor_specific_chargeinfo = 0;
|
|
|
static int ro_session_hash_size = 4096;
|
|
|
int ro_timer_buffer = 5;
|
|
|
int interim_request_credits = 30;
|
|
@@ -84,6 +87,7 @@ static int mod_child_init(int);
|
|
|
static void mod_destroy(void);
|
|
|
|
|
|
static int w_ro_ccr(struct sip_msg *msg, char* route_name, char* direction, int reservation_units, char* incoming_trunk_id, char* outgoing_trunk_id);
|
|
|
+static int w_ro_ccr_stop(struct sip_msg *msg, char* direction, char* _code, char* _reason);
|
|
|
//void ro_session_ontimeout(struct ro_tl *tl);
|
|
|
|
|
|
|
|
@@ -91,10 +95,12 @@ int create_response_avp_string(char* name, str* val);
|
|
|
static int w_ro_set_session_id_avp(struct sip_msg *msg, char *str1, char *str2);
|
|
|
|
|
|
static int ro_fixup(void **param, int param_no);
|
|
|
+static int ro_fixup_stop(void **param, int param_no);
|
|
|
|
|
|
static cmd_export_t cmds[] = {
|
|
|
{ "Ro_CCR", (cmd_function) w_ro_ccr, 5, ro_fixup, 0, REQUEST_ROUTE },
|
|
|
- { "Ro_set_session_id_avp", (cmd_function) w_ro_set_session_id_avp, 0, 0, 0, REQUEST_ROUTE | ONREPLY_ROUTE },
|
|
|
+ { "Ro_CCR_Stop",(cmd_function) w_ro_ccr_stop, 3, ro_fixup_stop, 0, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
|
|
|
+ { "Ro_set_session_id_avp", (cmd_function) w_ro_set_session_id_avp, 0, 0, 0, REQUEST_ROUTE | ONREPLY_ROUTE },
|
|
|
{ 0, 0, 0, 0, 0, 0 }
|
|
|
};
|
|
|
|
|
@@ -127,6 +133,8 @@ static param_export_t params[] = {
|
|
|
{ "db_mode", INT_PARAM, &ro_db_mode_param },
|
|
|
{ "db_url", PARAM_STRING, &db_url },
|
|
|
{ "db_update_period", INT_PARAM, &db_update_period },
|
|
|
+ { "vendor_specific_chargeinfo", INT_PARAM, &vendor_specific_chargeinfo }, /* VSI for extra charing info in Ro */
|
|
|
+ { "vendor_specific_id", INT_PARAM, &vendor_specific_id }, /* VSI for extra charing info in Ro */
|
|
|
{ 0, 0, 0 }
|
|
|
};
|
|
|
|
|
@@ -355,11 +363,93 @@ static int w_ro_set_session_id_avp(struct sip_msg *msg, char *str1, char *str2)
|
|
|
//set avp response with session id
|
|
|
res = create_response_avp_string("ro_session_id", &ro_session->ro_session_id);
|
|
|
dlgb.release_dlg(dlg);
|
|
|
+ unref_ro_session(ro_session, 1);
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
+static int w_ro_ccr_stop(struct sip_msg *msg, char* c_direction, char* _code, char* _reason) {
|
|
|
+ struct ro_session* ro_session;
|
|
|
+ struct ro_session_entry *ro_session_entry;
|
|
|
+ unsigned int h_entry;
|
|
|
+ str s_code, s_reason;
|
|
|
+ unsigned int code;
|
|
|
+ int dir = 0; /*any side*/
|
|
|
+
|
|
|
+ LM_DBG("Inside Ro_CCR_Stop with direction [%s]\n", c_direction);
|
|
|
+ if (strlen(c_direction) == 4) {
|
|
|
+ if (c_direction[0] == 'O' || c_direction[0] == 'o') {
|
|
|
+ dir = RO_ORIG_DIRECTION;
|
|
|
+ } else {
|
|
|
+ dir = RO_TERM_DIRECTION;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ LM_ERR("Unknown direction [%s] to terminate\n", c_direction);
|
|
|
+ return RO_RETURN_FALSE;
|
|
|
+ }
|
|
|
+ struct dlg_cell* dlg = dlgb.get_dlg(msg);
|
|
|
+ if (!dlg) {
|
|
|
+ LM_ERR("Unable to find dialog to send CCR STOP record\n");
|
|
|
+ return RO_RETURN_ERROR;
|
|
|
+ }
|
|
|
|
|
|
+ if (get_str_fparam(&s_code, msg, (fparam_t*) _code) < 0) {
|
|
|
+ LM_ERR("failed to get code\n");
|
|
|
+ return RO_RETURN_ERROR;
|
|
|
+ }
|
|
|
+ LM_DBG("Code is [%.*s]\n", s_code.len, s_code.s);
|
|
|
+ if (get_str_fparam(&s_reason, msg, (fparam_t*) _reason) < 0) {
|
|
|
+ LM_ERR("failed to get reason\n");
|
|
|
+ return RO_RETURN_ERROR;
|
|
|
+ }
|
|
|
|
|
|
+ if (str2int(&s_code, &code) != 0) {
|
|
|
+ LM_ERR("Bad response code: [%.*s]\n", s_code.len, s_code.s);
|
|
|
+ return RO_RETURN_FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+// switch (code) {
|
|
|
+// case 486:
|
|
|
+// termcode = VS_TERMCODE_BUSYHERE;
|
|
|
+// break;
|
|
|
+// case 487:
|
|
|
+// termcode = VS_TERMCODE_CANCELLED;
|
|
|
+// break;
|
|
|
+// case 480:
|
|
|
+// case 408:
|
|
|
+// /* subscriber not available */
|
|
|
+// termcode = VS_TERMCODE_NOTFOUND;
|
|
|
+// break;
|
|
|
+// }
|
|
|
+
|
|
|
+ LM_DBG("Sending Stop record with code [%d] and reason [%.*s]\n", code, s_reason.len, s_reason.s);
|
|
|
+
|
|
|
+ LM_DBG("Found DLG [%d : %d]\n", dlg->h_id, dlg->h_entry);
|
|
|
+
|
|
|
+ ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, dir, 0);
|
|
|
+ if (ro_session == NULL) {
|
|
|
+ LM_DBG("no ro_session - ignoring\n");
|
|
|
+ return RO_RETURN_TRUE;
|
|
|
+ }
|
|
|
+ h_entry = ro_session->h_entry;
|
|
|
+ ro_session_entry = &(ro_session_table->entries[h_entry]);
|
|
|
+
|
|
|
+ ro_session_lock(ro_session_table, ro_session_entry);
|
|
|
+
|
|
|
+ if (ro_session->ccr_sent == 1) {
|
|
|
+ LM_DBG("Ro CCR already sent for session [%.*s]\n", ro_session->ro_session_id.len, ro_session->ro_session_id.s);
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ send_ccr_stop_with_param(ro_session, code, &s_reason);
|
|
|
+ //TODO = check the CCR was sent successfully.
|
|
|
+ LM_DBG("Setting Ro session [%.*s] ccr_sent to 1\n", ro_session->ro_session_id.len, ro_session->ro_session_id.s);
|
|
|
+ ro_session->ccr_sent = 1;
|
|
|
+ ro_session->active = -1;
|
|
|
+// counter_add(ims_charging_cnts_h.active_ro_sessions, -1);
|
|
|
+done:
|
|
|
+ unref_ro_session_unsafe(ro_session, 1, ro_session_entry);
|
|
|
+ ro_session_unlock(ro_session_table, ro_session_entry);
|
|
|
+ return RO_RETURN_TRUE;
|
|
|
+}
|
|
|
|
|
|
static int w_ro_ccr(struct sip_msg *msg, char* c_route_name, char* c_direction, int reservation_units, char* c_incoming_trunk_id, char* c_outgoing_trunk_id) {
|
|
|
/* PSEUDOCODE/NOTES
|
|
@@ -544,3 +634,10 @@ static int ro_fixup(void **param, int param_no) {
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+static int ro_fixup_stop(void **param, int param_no) {
|
|
|
+ if (param_no == 2 || param_no == 3) {
|
|
|
+ return fixup_var_pve_12(param, param_no);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|