|
@@ -75,7 +75,7 @@
|
|
|
|
|
|
MODULE_VERSION
|
|
|
|
|
|
-extern gen_lock_t* process_lock; /* lock on the process table */
|
|
|
+ extern gen_lock_t* process_lock; /* lock on the process table */
|
|
|
|
|
|
str orig_session_key = {"originating", 11};
|
|
|
str term_session_key = {"terminating", 11};
|
|
@@ -101,8 +101,7 @@ static int mod_child_init(int);
|
|
|
static void mod_destroy(void);
|
|
|
|
|
|
static int fixup_aar_register(void** param, int param_no);
|
|
|
-
|
|
|
-static void free_dialog_data(void *data);
|
|
|
+static int fixup_aar(void** param, int param_no);
|
|
|
|
|
|
int * callback_singleton; /*< Callback singleton */
|
|
|
|
|
@@ -114,12 +113,12 @@ char* rx_forced_peer_s = "";
|
|
|
str rx_forced_peer;
|
|
|
|
|
|
/* commands wrappers and fixups */
|
|
|
-static int w_rx_aar(struct sip_msg *msg, char* direction, char *bar);
|
|
|
-static int w_rx_aar_register(struct sip_msg *msg, char* str1, char *bar);
|
|
|
+static int w_rx_aar(struct sip_msg *msg, char *route, char* direction, char *bar);
|
|
|
+static int w_rx_aar_register(struct sip_msg *msg, char *route, char* str1, char *bar);
|
|
|
|
|
|
static cmd_export_t cmds[] = {
|
|
|
- { "Rx_AAR", (cmd_function) w_rx_aar, 1, 0, 0, REQUEST_ROUTE | ONREPLY_ROUTE},
|
|
|
- { "Rx_AAR_Register", (cmd_function) w_rx_aar_register, 1, fixup_aar_register, 0, REQUEST_ROUTE},
|
|
|
+ { "Rx_AAR", (cmd_function) w_rx_aar, 2, fixup_aar, 0, REQUEST_ROUTE | ONREPLY_ROUTE},
|
|
|
+ { "Rx_AAR_Register", (cmd_function) w_rx_aar_register, 2, fixup_aar_register, 0, REQUEST_ROUTE},
|
|
|
{ 0, 0, 0, 0, 0, 0}
|
|
|
};
|
|
|
|
|
@@ -134,9 +133,9 @@ static param_export_t params[] = {
|
|
|
};
|
|
|
|
|
|
stat_export_t mod_stats[] = {
|
|
|
- {"aar_avg_response_time" , STAT_IS_FUNC, (stat_var**)get_avg_aar_response_time },
|
|
|
- {"aar_timeouts" , 0, (stat_var**)&stat_aar_timeouts },
|
|
|
- {0,0,0}
|
|
|
+ {"aar_avg_response_time", STAT_IS_FUNC, (stat_var**) get_avg_aar_response_time},
|
|
|
+ {"aar_timeouts", 0, (stat_var**) & stat_aar_timeouts},
|
|
|
+ {0, 0, 0}
|
|
|
};
|
|
|
|
|
|
/** module exports */
|
|
@@ -156,7 +155,7 @@ int fix_parameters() {
|
|
|
rx_forced_peer.s = rx_forced_peer_s;
|
|
|
rx_forced_peer.len = strlen(rx_forced_peer_s);
|
|
|
|
|
|
- return RX_RETURN_TRUE;
|
|
|
+ return CSCF_RETURN_TRUE;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -169,16 +168,16 @@ static int mod_init(void) {
|
|
|
goto error;
|
|
|
|
|
|
#ifdef STATISTICS
|
|
|
- /* register statistics */
|
|
|
- if (register_module_stats( exports.name, mod_stats)!=0 ) {
|
|
|
- LM_ERR("failed to register core statistics\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
-
|
|
|
- if (!register_stats()){
|
|
|
- LM_ERR("Unable to register statistics\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
+ /* register statistics */
|
|
|
+ if (register_module_stats(exports.name, mod_stats) != 0) {
|
|
|
+ LM_ERR("failed to register core statistics\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!register_stats()) {
|
|
|
+ LM_ERR("Unable to register statistics\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
#endif
|
|
|
|
|
|
callback_singleton = shm_malloc(sizeof (int));
|
|
@@ -216,12 +215,12 @@ static int mod_init(void) {
|
|
|
bind_usrloc = (bind_usrloc_t) find_export("ul_bind_ims_usrloc_pcscf", 1, 0);
|
|
|
if (!bind_usrloc) {
|
|
|
LM_ERR("can't bind usrloc_pcscf\n");
|
|
|
- return RX_RETURN_FALSE;
|
|
|
+ return CSCF_RETURN_FALSE;
|
|
|
}
|
|
|
|
|
|
if (bind_usrloc(&ul) < 0) {
|
|
|
LM_ERR("can't bind to usrloc pcscf\n");
|
|
|
- return RX_RETURN_FALSE;
|
|
|
+ return CSCF_RETURN_FALSE;
|
|
|
}
|
|
|
LM_DBG("Successfully bound to PCSCF Usrloc module\n");
|
|
|
|
|
@@ -236,7 +235,7 @@ static int mod_init(void) {
|
|
|
return 0;
|
|
|
error:
|
|
|
LM_ERR("Failed to initialise ims_qos module\n");
|
|
|
- return RX_RETURN_FALSE;
|
|
|
+ return CSCF_RETURN_FALSE;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -294,7 +293,7 @@ void callback_for_cdp_session(int event, void *session) {
|
|
|
//only put the events we care about on the event stack
|
|
|
if (event == AUTH_EV_SESSION_TIMEOUT ||
|
|
|
event == AUTH_EV_SESSION_GRACE_TIMEOUT ||
|
|
|
- event == AUTH_EV_SESSION_LIFETIME_TIMEOUT ||
|
|
|
+ event == AUTH_EV_RECV_ASR ||
|
|
|
event == AUTH_EV_SERVICE_TERMINATED) {
|
|
|
|
|
|
LOG(L_DBG, "callback_for_cdp session(): called with event %d and session id [%.*s]\n", event, rx_session_id->len, rx_session_id->s);
|
|
@@ -349,19 +348,6 @@ AAAMessage* callback_cdp_request(AAAMessage *request, void *param) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void free_dialog_data(void *data) {
|
|
|
- str *rx_session_id = (str*) data;
|
|
|
- if (rx_session_id) {
|
|
|
- if (rx_session_id->s) {
|
|
|
- shm_free(rx_session_id->s);
|
|
|
- rx_session_id->s = 0;
|
|
|
- }
|
|
|
- shm_free(rx_session_id);
|
|
|
- rx_session_id = 0;
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
void callback_dialog_terminated(struct dlg_cell* dlg, int type, struct dlg_cb_params * params) {
|
|
|
LM_DBG("Dialog has ended - we need to terminate Rx bearer session\n");
|
|
|
|
|
@@ -405,28 +391,56 @@ void callback_pcscf_contact_cb(struct pcontact *c, int type, void *param) {
|
|
|
/* Wrapper to send AAR from config file - this only allows for AAR for calls - not register, which uses r_rx_aar_register
|
|
|
* return: 1 - success, <=0 failure. 2 - message not a AAR generating message (ie proceed without PCC if you wish)
|
|
|
*/
|
|
|
-static int w_rx_aar(struct sip_msg *msg, char* direction, char* bar) {
|
|
|
+static int w_rx_aar(struct sip_msg *msg, char *route, char* str1, char* bar) {
|
|
|
+
|
|
|
+ int ret = CSCF_RETURN_ERROR;
|
|
|
struct cell *t;
|
|
|
- AAAMessage* resp;
|
|
|
+
|
|
|
AAASession* auth_session;
|
|
|
rx_authsessiondata_t* rx_authdata_p = 0;
|
|
|
- unsigned int result = AAA_SUCCESS;
|
|
|
str *rx_session_id;
|
|
|
str callid = {0, 0};
|
|
|
str ftag = {0, 0};
|
|
|
str ttag = {0, 0};
|
|
|
+
|
|
|
+ str route_name;
|
|
|
+
|
|
|
+ cfg_action_t* cfg_action = 0;
|
|
|
+ saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
|
|
|
+ char* direction = str1;
|
|
|
+ if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
|
|
|
+ LM_ERR("no async route block for assign_server_unreg\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
|
|
|
+ int ri = route_get(&main_rt, route_name.s);
|
|
|
+ if (ri < 0) {
|
|
|
+ LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ cfg_action = main_rt.rlist[ri];
|
|
|
+ if (cfg_action == NULL) {
|
|
|
+ LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ LM_DBG("Rx AAR called\n");
|
|
|
+ //create the default return code AVP
|
|
|
+ create_return_code(ret);
|
|
|
|
|
|
//We don't ever do AAR on request for calling scenario...
|
|
|
if (msg->first_line.type != SIP_REPLY) {
|
|
|
LM_DBG("Can't do AAR for call session in request\n");
|
|
|
- goto error;
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
}
|
|
|
|
|
|
//is it appropriate to send AAR at this stage?
|
|
|
t = tmb.t_gett();
|
|
|
- if (!t) {
|
|
|
+ if (t == NULL || t == T_UNDEFINED) {
|
|
|
LM_WARN("Cannot get transaction for AAR based on SIP Request\n");
|
|
|
- goto aarna;
|
|
|
+ //goto aarna;
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
}
|
|
|
|
|
|
//we dont apply QoS if its not a reply to an INVITE! or UPDATE or PRACK!
|
|
@@ -435,34 +449,85 @@ static int w_rx_aar(struct sip_msg *msg, char* direction, char* bar) {
|
|
|
|| memcmp(t->method.s, "UPDATE", 6) == 0))) {
|
|
|
if (cscf_get_content_length(msg) == 0
|
|
|
|| cscf_get_content_length(t->uas.request) == 0) {
|
|
|
- goto aarna; //AAR na if we dont have offer/answer pair
|
|
|
+ LM_DBG("No SDP offer answer -> therefore we can not do Rx AAR");
|
|
|
+ //goto aarna; //AAR na if we dont have offer/answer pair
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
}
|
|
|
} else {
|
|
|
- goto aarna;
|
|
|
+ LM_DBG("Message is not response to INVITE, PRACK or UPDATE -> therefore we do not Rx AAR");
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
}
|
|
|
|
|
|
/* get callid, from and to tags to be able to identify dialog */
|
|
|
callid = cscf_get_call_id(msg, 0);
|
|
|
if (callid.len <= 0 || !callid.s) {
|
|
|
LM_ERR("unable to get callid\n");
|
|
|
- goto error;
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
}
|
|
|
if (!cscf_get_from_tag(msg, &ftag)) {
|
|
|
LM_ERR("Unable to get ftag\n");
|
|
|
- goto error;
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
}
|
|
|
if (!cscf_get_to_tag(msg, &ttag)) {
|
|
|
LM_ERR("Unable to get ttag\n");
|
|
|
- goto error;
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
}
|
|
|
|
|
|
//check to see that this is not a result of a retransmission in reply route only
|
|
|
if (msg->cseq == NULL
|
|
|
&& ((parse_headers(msg, HDR_CSEQ_F, 0) == -1) || (msg->cseq == NULL))) {
|
|
|
LM_ERR("No Cseq header found - aborting\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
-
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ saved_t_data = (saved_transaction_t*) shm_malloc(sizeof (saved_transaction_t));
|
|
|
+ if (!saved_t_data) {
|
|
|
+ LM_ERR("Unable to allocate memory for transaction data, trying to send AAR\n");
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+ memset(saved_t_data, 0, sizeof (saved_transaction_t));
|
|
|
+ saved_t_data->act = cfg_action;
|
|
|
+ //OTHER parms need after async response set here
|
|
|
+ //store call id
|
|
|
+ saved_t_data->callid.s = (char*) shm_malloc(callid.len + 1);
|
|
|
+ if (!saved_t_data->callid.s) {
|
|
|
+ LM_ERR("no more memory trying to save transaction state : callid\n");
|
|
|
+ shm_free(saved_t_data);
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+ memset(saved_t_data->callid.s, 0, callid.len + 1);
|
|
|
+ memcpy(saved_t_data->callid.s, callid.s, callid.len);
|
|
|
+ saved_t_data->callid.len = callid.len;
|
|
|
+
|
|
|
+ //store ttag
|
|
|
+ saved_t_data->ttag.s = (char*) shm_malloc(ttag.len + 1);
|
|
|
+ if (!saved_t_data->ttag.s) {
|
|
|
+ LM_ERR("no more memory trying to save transaction state : ttag\n");
|
|
|
+ shm_free(saved_t_data);
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+ memset(saved_t_data->ttag.s, 0, ttag.len + 1);
|
|
|
+ memcpy(saved_t_data->ttag.s, ttag.s, ttag.len);
|
|
|
+ saved_t_data->ttag.len = ttag.len;
|
|
|
+
|
|
|
+ //store ftag
|
|
|
+ saved_t_data->ftag.s = (char*) shm_malloc(ftag.len + 1);
|
|
|
+ if (!saved_t_data->ftag.s) {
|
|
|
+ LM_ERR("no more memory trying to save transaction state : ftag\n");
|
|
|
+ shm_free(saved_t_data);
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+ memset(saved_t_data->ftag.s, 0, ftag.len + 1);
|
|
|
+ memcpy(saved_t_data->ftag.s, ftag.s, ftag.len);
|
|
|
+ saved_t_data->ftag.len = ftag.len;
|
|
|
+
|
|
|
+ //store branch
|
|
|
+ int branch;
|
|
|
+ if (tmb.t_check( msg , &branch )==-1){
|
|
|
+ LOG(L_ERR, "ERROR: t_suspend: failed find UAC branch\n");
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
//Check that we dont already have an auth session for this specific dialog
|
|
|
//if not we create a new one and attach it to the dialog (via session ID).
|
|
|
enum dialog_direction dlg_direction = get_dialog_direction(direction);
|
|
@@ -504,62 +569,44 @@ static int w_rx_aar(struct sip_msg *msg, char* direction, char* bar) {
|
|
|
LM_DBG("Attached CDP auth session [%.*s] for Rx to dialog in %s mode\n", auth_session->id.len, auth_session->id.s, direction);
|
|
|
} else {
|
|
|
LM_DBG("Update AAR session for this dialog in mode %s\n", direction);
|
|
|
- //TODO - what to do on updates - reinvites, etc
|
|
|
- goto aarna; //TODO: for now we ignore
|
|
|
+ if (saved_t_data)
|
|
|
+ free_saved_transaction_global_data(saved_t_data); //only free global data if no AARs were sent. if one was sent we have to rely on the callback (CDP) to free
|
|
|
+ create_return_code(CSCF_RETURN_TRUE);
|
|
|
+ return CSCF_RETURN_TRUE;
|
|
|
}
|
|
|
|
|
|
- resp = rx_send_aar(t->uas.request, msg, auth_session, &callid, &ftag, &ttag,
|
|
|
- direction, &rx_authdata_p);
|
|
|
-
|
|
|
- if (!resp) {
|
|
|
- LM_ERR("No response received for AAR request\n");
|
|
|
- goto error;
|
|
|
+ LM_DBG("Suspending SIP TM transaction\n");
|
|
|
+ if (tmb.t_suspend(msg, &saved_t_data->tindex, &saved_t_data->tlabel) < 0) {
|
|
|
+ LM_ERR("failed to suspend the TM processing\n");
|
|
|
+ free_saved_transaction_global_data(saved_t_data);
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
}
|
|
|
|
|
|
- if (!rx_authdata_p) {
|
|
|
- LM_ERR("Rx: mod.c: error creating new rx_auth_data\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
- //
|
|
|
- // /* Process the response to AAR, retrieving result code and associated Rx session ID */
|
|
|
- if (rx_process_aaa(resp, &result) < 0) {
|
|
|
- LM_DBG("Failed to process AAA from PCRF\n");
|
|
|
- cdpb.AAAFreeMessage(&resp);
|
|
|
- goto error;
|
|
|
- }
|
|
|
- cdpb.AAAFreeMessage(&resp);
|
|
|
-
|
|
|
+ LM_DBG("Sending Rx AAR");
|
|
|
+ ret = rx_send_aar(t->uas.request, msg, auth_session, direction, saved_t_data);
|
|
|
|
|
|
- if (result >= 2000 && result < 3000) {
|
|
|
- LM_DBG("Success, received code: [%i] from PCRF for AAR request\n", result);
|
|
|
-
|
|
|
- str * passed_rx_session_id = shm_malloc(sizeof (struct _str));
|
|
|
+ if (!ret) {
|
|
|
+ LM_ERR("Failed to send AAR\n");
|
|
|
+ tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
|
|
|
+ goto error;
|
|
|
|
|
|
- passed_rx_session_id->s = 0;
|
|
|
- passed_rx_session_id->len = 0;
|
|
|
- STR_SHM_DUP(*passed_rx_session_id, auth_session->id, "cb_passed_rx_session_id");
|
|
|
|
|
|
- LM_DBG("passed rx session id %.*s", passed_rx_session_id->len, passed_rx_session_id->s);
|
|
|
+ } else {
|
|
|
+ LM_DBG("Successful async send of AAR\n");
|
|
|
+ return CSCF_RETURN_BREAK; //on success we break - because rest of cfg file will be executed by async process
|
|
|
+ }
|
|
|
|
|
|
- dlgb.register_dlgcb_nodlg(&callid, &ftag, &ttag, DLGCB_TERMINATED | DLGCB_DESTROY | DLGCB_EXPIRED, callback_dialog_terminated, (void*) (passed_rx_session_id), free_dialog_data);
|
|
|
+error:
|
|
|
+ LM_ERR("Error trying to send AAR (calling)\n");
|
|
|
+ if (saved_t_data)
|
|
|
+ free_saved_transaction_global_data(saved_t_data); //only free global data if no AARs were sent. if one was sent we have to rely on the callback (CDP) to free
|
|
|
+ //otherwise the callback will segfault
|
|
|
|
|
|
- return RX_RETURN_TRUE;
|
|
|
- } else {
|
|
|
- LM_DBG("Received negative reply from PCRF for AAR Request\n");
|
|
|
- //we don't free rx_authdata_p here - it is free-ed when the CDP session expires
|
|
|
- goto error; // if its not a success then that means i want to reject this call!
|
|
|
- }
|
|
|
-out_of_memory:
|
|
|
- error :
|
|
|
- LM_ERR("Error trying to send AAR (calling)\n");
|
|
|
- return RX_RETURN_FALSE;
|
|
|
-aarna:
|
|
|
- LM_DBG("Policy and Charging Control non-applicable\n");
|
|
|
- return RX_RETURN_AAR_NA;
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
}
|
|
|
|
|
|
/* Wrapper to send AAR from config file - only used for registration */
|
|
|
-static int w_rx_aar_register(struct sip_msg *msg, char* str1, char* bar) {
|
|
|
+static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char* bar) {
|
|
|
|
|
|
int ret = CSCF_RETURN_ERROR;
|
|
|
struct pcontact_info ci;
|
|
@@ -571,14 +618,32 @@ static int w_rx_aar_register(struct sip_msg *msg, char* str1, char* bar) {
|
|
|
AAASession* auth;
|
|
|
rx_authsessiondata_t* rx_regsession_data_p;
|
|
|
cfg_action_t* cfg_action = 0;
|
|
|
+ str route_name;
|
|
|
char* p;
|
|
|
int aar_sent = 0;
|
|
|
- saved_transaction_local_t* local_data = 0; //data to be shared across all async calls
|
|
|
- saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
|
|
|
- aar_param_t* ap = (aar_param_t*) str1;
|
|
|
- udomain_t* domain_t = ap->domain;
|
|
|
- cfg_action = ap->paction->next;
|
|
|
- int is_rereg = 0; //is this a reg/re-reg
|
|
|
+ saved_transaction_local_t* local_data = 0; //data to be shared across all async calls
|
|
|
+ saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
|
|
|
+
|
|
|
+ if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
|
|
|
+ LM_ERR("no async route block for assign_server_unreg\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
|
|
|
+ int ri = route_get(&main_rt, route_name.s);
|
|
|
+ if (ri < 0) {
|
|
|
+ LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ cfg_action = main_rt.rlist[ri];
|
|
|
+ if (cfg_action == NULL) {
|
|
|
+ LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ udomain_t* domain_t = (udomain_t*) str1;
|
|
|
+
|
|
|
+ int is_rereg = 0; //is this a reg/re-reg
|
|
|
|
|
|
LM_DBG("Rx AAR Register called\n");
|
|
|
|
|
@@ -619,60 +684,60 @@ static int w_rx_aar_register(struct sip_msg *msg, char* str1, char* bar) {
|
|
|
//if ((cscf_get_expires(msg) == 0)) {
|
|
|
LM_DBG("This is a de registration\n");
|
|
|
LM_DBG("We ignore it as these are dealt with by usrloc callbacks \n");
|
|
|
- create_return_code(RX_RETURN_TRUE);
|
|
|
- return RX_RETURN_TRUE;
|
|
|
+ create_return_code(CSCF_RETURN_TRUE);
|
|
|
+ return CSCF_RETURN_TRUE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//before we continue, make sure we have a transaction to work with (viz. cdp async)
|
|
|
- t = tmb.t_gett();
|
|
|
- if (t == NULL || t == T_UNDEFINED) {
|
|
|
- if (tmb.t_newtran(msg) < 0) {
|
|
|
- LM_ERR("cannot create the transaction for UAR async\n");
|
|
|
- return CSCF_RETURN_ERROR;
|
|
|
- }
|
|
|
- t = tmb.t_gett();
|
|
|
- if (t == NULL || t == T_UNDEFINED) {
|
|
|
- LM_ERR("cannot lookup the transaction\n");
|
|
|
- return CSCF_RETURN_ERROR;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- saved_t_data = (saved_transaction_t*)shm_malloc(sizeof(saved_transaction_t));
|
|
|
- if (!saved_t_data){
|
|
|
- LM_ERR("Unable to allocate memory for transaction data, trying to send AAR\n");
|
|
|
- return CSCF_RETURN_ERROR;
|
|
|
- }
|
|
|
- memset(saved_t_data,0,sizeof(saved_transaction_t));
|
|
|
- saved_t_data->act = cfg_action;
|
|
|
- saved_t_data->domain = domain_t;
|
|
|
- saved_t_data->lock = lock_alloc();
|
|
|
- if (saved_t_data->lock == NULL) {
|
|
|
- LM_ERR("unable to allocate init lock for saved_t_transaction reply counter\n");
|
|
|
- return CSCF_RETURN_ERROR;
|
|
|
- }
|
|
|
- if (lock_init(saved_t_data->lock) == NULL) {
|
|
|
- LM_ERR("unable to init lock for saved_t_transaction reply counter\n");
|
|
|
- return CSCF_RETURN_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- LM_DBG("Suspending SIP TM transaction\n");
|
|
|
- if (tmb.t_suspend(msg, &saved_t_data->tindex, &saved_t_data->tlabel) < 0) {
|
|
|
- LM_ERR("failed to suspend the TM processing\n");
|
|
|
- free_saved_transaction_global_data(saved_t_data);
|
|
|
- return CSCF_RETURN_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- LM_DBG("Successfully suspended transaction\n");
|
|
|
-
|
|
|
- //now get the contacts in the REGISTER and do AAR for each one.
|
|
|
+ t = tmb.t_gett();
|
|
|
+ if (t == NULL || t == T_UNDEFINED) {
|
|
|
+ if (tmb.t_newtran(msg) < 0) {
|
|
|
+ LM_ERR("cannot create the transaction for UAR async\n");
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+ t = tmb.t_gett();
|
|
|
+ if (t == NULL || t == T_UNDEFINED) {
|
|
|
+ LM_ERR("cannot lookup the transaction\n");
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ saved_t_data = (saved_transaction_t*) shm_malloc(sizeof (saved_transaction_t));
|
|
|
+ if (!saved_t_data) {
|
|
|
+ LM_ERR("Unable to allocate memory for transaction data, trying to send AAR\n");
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+ memset(saved_t_data, 0, sizeof (saved_transaction_t));
|
|
|
+ saved_t_data->act = cfg_action;
|
|
|
+ saved_t_data->domain = domain_t;
|
|
|
+ saved_t_data->lock = lock_alloc();
|
|
|
+ if (saved_t_data->lock == NULL) {
|
|
|
+ LM_ERR("unable to allocate init lock for saved_t_transaction reply counter\n");
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+ if (lock_init(saved_t_data->lock) == NULL) {
|
|
|
+ LM_ERR("unable to init lock for saved_t_transaction reply counter\n");
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ LM_DBG("Suspending SIP TM transaction\n");
|
|
|
+ if (tmb.t_suspend(msg, &saved_t_data->tindex, &saved_t_data->tlabel) < 0) {
|
|
|
+ LM_ERR("failed to suspend the TM processing\n");
|
|
|
+ free_saved_transaction_global_data(saved_t_data);
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ LM_DBG("Successfully suspended transaction\n");
|
|
|
+
|
|
|
+ //now get the contacts in the REGISTER and do AAR for each one.
|
|
|
cb = cscf_parse_contacts(msg);
|
|
|
if (!cb || (!cb->contacts && !cb->star)) {
|
|
|
LM_DBG("No contact headers in Register message\n");
|
|
|
goto error;
|
|
|
}
|
|
|
|
|
|
- lock_get(saved_t_data->lock); //we lock here to make sure we send all requests before processing replies asynchronously
|
|
|
+ lock_get(saved_t_data->lock); //we lock here to make sure we send all requests before processing replies asynchronously
|
|
|
for (h = msg->contact; h; h = h->next) {
|
|
|
if (h->type == HDR_CONTACT_T && h->parsed) {
|
|
|
for (c = ((contact_body_t*) h->parsed)->contacts; c; c = c->next) {
|
|
@@ -685,7 +750,7 @@ static int w_rx_aar_register(struct sip_msg *msg, char* str1, char* bar) {
|
|
|
} else if (pcontact->reg_state == PCONTACT_REG_PENDING
|
|
|
|| pcontact->reg_state == PCONTACT_REGISTERED) { //NEW reg request
|
|
|
LM_DBG("Contact [%.*s] exists and is in state PCONTACT_REG_PENDING or PCONTACT_REGISTERED\n"
|
|
|
- , pcontact->aor.len, pcontact->aor.s);
|
|
|
+ , pcontact->aor.len, pcontact->aor.s);
|
|
|
|
|
|
//get IP address from contact
|
|
|
struct sip_uri puri;
|
|
@@ -745,12 +810,12 @@ static int w_rx_aar_register(struct sip_msg *msg, char* str1, char* bar) {
|
|
|
}
|
|
|
|
|
|
//we are ready to send the AAR async. lets save the local data data
|
|
|
- int local_data_len = sizeof(saved_transaction_local_t) + c->uri.len + auth->id.len;
|
|
|
+ int local_data_len = sizeof (saved_transaction_local_t) + c->uri.len + auth->id.len;
|
|
|
local_data = shm_malloc(local_data_len);
|
|
|
if (!local_data) {
|
|
|
- LM_ERR("unable to alloc memory for local data, trying to send AAR Register\n");
|
|
|
- lock_release(saved_t_data->lock);
|
|
|
- goto error;
|
|
|
+ LM_ERR("unable to alloc memory for local data, trying to send AAR Register\n");
|
|
|
+ lock_release(saved_t_data->lock);
|
|
|
+ goto error;
|
|
|
}
|
|
|
memset(local_data, 0, local_data_len);
|
|
|
|
|
@@ -761,32 +826,36 @@ static int w_rx_aar_register(struct sip_msg *msg, char* str1, char* bar) {
|
|
|
local_data->contact.s = p;
|
|
|
local_data->contact.len = c->uri.len;
|
|
|
memcpy(p, c->uri.s, c->uri.len);
|
|
|
- p+=c->uri.len;
|
|
|
+ p += c->uri.len;
|
|
|
|
|
|
local_data->auth_session_id.s = p;
|
|
|
local_data->auth_session_id.len = auth->id.len;
|
|
|
memcpy(p, auth->id.s, auth->id.len);
|
|
|
- p+=auth->id.len;
|
|
|
+ p += auth->id.len;
|
|
|
|
|
|
- if (p!=( ((char*)local_data) + local_data_len) ) {
|
|
|
- LM_CRIT("buffer overflow\n");
|
|
|
- free_saved_transaction_data(local_data);
|
|
|
- goto error;
|
|
|
+ if (p != (((char*) local_data) + local_data_len)) {
|
|
|
+ LM_CRIT("buffer overflow\n");
|
|
|
+ free_saved_transaction_data(local_data);
|
|
|
+ goto error;
|
|
|
}
|
|
|
|
|
|
LM_DBG("Calling send aar register");
|
|
|
- ret = rx_send_aar_register(msg, auth, &puri.host, &ip_version, &c->uri, local_data); //returns a locked rx auth object
|
|
|
+
|
|
|
+ //TODOD remove - no longer user AOR parm
|
|
|
+ //ret = rx_send_aar_register(msg, auth, &puri.host, &ip_version, &c->uri, local_data); //returns a locked rx auth object
|
|
|
+ ret = rx_send_aar_register(msg, auth, &puri.host, &ip_version, local_data); //returns a locked rx auth object
|
|
|
+
|
|
|
ul.unlock_udomain(domain_t, &c->uri);
|
|
|
|
|
|
if (!ret) {
|
|
|
- LM_ERR("Failed to send AAR\n");
|
|
|
- lock_release(saved_t_data->lock);
|
|
|
- free_saved_transaction_data(local_data); //free the local data becuase the CDP async request was not successful (we must free here)
|
|
|
- goto error;
|
|
|
+ LM_ERR("Failed to send AAR\n");
|
|
|
+ lock_release(saved_t_data->lock);
|
|
|
+ free_saved_transaction_data(local_data); //free the local data becuase the CDP async request was not successful (we must free here)
|
|
|
+ goto error;
|
|
|
} else {
|
|
|
- aar_sent = 1;
|
|
|
- //before we send - bump up the reply counter
|
|
|
- saved_t_data->answers_not_received++; //we dont need to lock as we already hold the lock above
|
|
|
+ aar_sent = 1;
|
|
|
+ //before we send - bump up the reply counter
|
|
|
+ saved_t_data->answers_not_received++; //we dont need to lock as we already hold the lock above
|
|
|
}
|
|
|
} else {
|
|
|
//contact exists - this is a re-registration, for now we just ignore this
|
|
@@ -796,11 +865,11 @@ static int w_rx_aar_register(struct sip_msg *msg, char* str1, char* bar) {
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
- if (h->type == HDR_CONTACT_T) { //means we couldnt parse the contact - this is an error
|
|
|
- LM_ERR("Failed to parse contact header\n");
|
|
|
- lock_release(saved_t_data->lock);
|
|
|
- goto error;
|
|
|
- }
|
|
|
+ if (h->type == HDR_CONTACT_T) { //means we couldnt parse the contact - this is an error
|
|
|
+ LM_ERR("Failed to parse contact header\n");
|
|
|
+ lock_release(saved_t_data->lock);
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
//all requests sent at this point - we can unlock the reply lock
|
|
@@ -811,46 +880,87 @@ static int w_rx_aar_register(struct sip_msg *msg, char* str1, char* bar) {
|
|
|
* 2. haven't needed to send ANY AAR's for ANY contacts
|
|
|
*/
|
|
|
if (aar_sent) {
|
|
|
- LM_DBG("Successful async send of AAR\n");
|
|
|
- return RX_RETURN_BREAK; //on success we break - because rest of cfg file will be executed by async process
|
|
|
+ LM_DBG("Successful async send of AAR\n");
|
|
|
+ return CSCF_RETURN_BREAK; //on success we break - because rest of cfg file will be executed by async process
|
|
|
} else {
|
|
|
- create_return_code(RX_RETURN_TRUE);
|
|
|
- free_saved_transaction_global_data(saved_t_data); //no aar sent so we must free the global data
|
|
|
- return RX_RETURN_TRUE;
|
|
|
+ create_return_code(CSCF_RETURN_TRUE);
|
|
|
+ tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
|
|
|
+ if (saved_t_data) {
|
|
|
+ free_saved_transaction_global_data(saved_t_data); //no aar sent so we must free the global data
|
|
|
+ }
|
|
|
+ //return CSCF_RETURN_ERROR;
|
|
|
+ return CSCF_RETURN_TRUE;
|
|
|
}
|
|
|
error:
|
|
|
LM_ERR("Error trying to send AAR\n");
|
|
|
- if (!aar_sent)
|
|
|
- if (saved_t_data)
|
|
|
- free_saved_transaction_global_data(saved_t_data); //only free global data if no AARs were sent. if one was sent we have to rely on the callback (CDP) to free
|
|
|
- //otherwise the callback will segfault
|
|
|
- return RX_RETURN_FALSE;
|
|
|
+ if (!aar_sent) {
|
|
|
+ tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
|
|
|
+ if (saved_t_data) {
|
|
|
+ free_saved_transaction_global_data(saved_t_data); //only free global data if no AARs were sent. if one was sent we have to rely on the callback (CDP) to free
|
|
|
+ //otherwise the callback will segfault
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return CSCF_RETURN_ERROR;
|
|
|
+ //return CSCF_RETURN_FALSE;
|
|
|
}
|
|
|
|
|
|
-static int fixup_aar_register(void** param, int param_no)
|
|
|
-{
|
|
|
- udomain_t* d;
|
|
|
- aar_param_t *ap;
|
|
|
-
|
|
|
- if(param_no!=1)
|
|
|
- return 0;
|
|
|
- ap = (aar_param_t*)pkg_malloc(sizeof(aar_param_t));
|
|
|
- if(ap==NULL)
|
|
|
- {
|
|
|
- LM_ERR("no more pkg\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- memset(ap, 0, sizeof(aar_param_t));
|
|
|
- ap->paction = get_action_from_param(param, param_no);
|
|
|
-
|
|
|
- if (ul.register_udomain((char*) *param, &d) < 0) {
|
|
|
- LM_ERR("failed to register domain\n");
|
|
|
- return E_UNSPEC;
|
|
|
- }
|
|
|
- ap->domain = d;
|
|
|
-
|
|
|
- *param = (void*)ap;
|
|
|
- return 0;
|
|
|
+static int fixup_aar_register(void** param, int param_no) {
|
|
|
+// udomain_t* d;
|
|
|
+// aar_param_t *ap;
|
|
|
+//
|
|
|
+// if (param_no != 1)
|
|
|
+// return 0;
|
|
|
+// ap = (aar_param_t*) pkg_malloc(sizeof (aar_param_t));
|
|
|
+// if (ap == NULL) {
|
|
|
+// LM_ERR("no more pkg\n");
|
|
|
+// return -1;
|
|
|
+// }
|
|
|
+// memset(ap, 0, sizeof (aar_param_t));
|
|
|
+// ap->paction = get_action_from_param(param, param_no);
|
|
|
+//
|
|
|
+// if (ul.register_udomain((char*) *param, &d) < 0) {
|
|
|
+// LM_ERR("failed to register domain\n");
|
|
|
+// return E_UNSPEC;
|
|
|
+// }
|
|
|
+// ap->domain = d;
|
|
|
+//
|
|
|
+// *param = (void*) ap;
|
|
|
+// return 0;
|
|
|
+ if (strlen((char*) *param) <= 0) {
|
|
|
+ LM_ERR("empty parameter %d not allowed\n", param_no);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (param_no == 1) { //route name - static or dynamic string (config vars)
|
|
|
+ if (fixup_spve_null(param, param_no) < 0)
|
|
|
+ return -1;
|
|
|
+ return 0;
|
|
|
+ } else if (param_no == 2) {
|
|
|
+ udomain_t* d;
|
|
|
+
|
|
|
+ if (ul.register_udomain((char*) *param, &d) < 0) {
|
|
|
+ LM_ERR("Error doing fixup on assign save");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ *param = (void*) d;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int fixup_aar(void** param, int param_no) {
|
|
|
+ if (strlen((char*) *param) <= 0) {
|
|
|
+ LM_ERR("empty parameter %d not allowed\n", param_no);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (param_no == 1) { //route name - static or dynamic string (config vars)
|
|
|
+ if (fixup_spve_null(param, param_no) < 0)
|
|
|
+ return -1;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/*create a return code to be passed back into config file*/
|