modules/ims_qos: new mod_param to add RTCP flow description for media flow
[sip-router] / modules / ims_qos / mod.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
5  * Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
6  * 
7  * The initial version of this code was written by Dragos Vingarzan
8  * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
9  * Fruanhofer Institute. It was and still is maintained in a separate
10  * branch of the original SER. We are therefore migrating it to
11  * Kamailio/SR and look forward to maintaining it from here on out.
12  * 2011/2012 Smile Communications, Pty. Ltd.
13  * ported/maintained/improved by 
14  * Jason Penton (jason(dot)penton(at)smilecoms.com and
15  * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
16  * effort to add full IMS support to Kamailio/SR using a new and
17  * improved architecture
18  * 
19  * NB: Alot of this code was originally part of OpenIMSCore,
20  * FhG Fokus. 
21  * Copyright (C) 2004-2006 FhG Fokus
22  * Thanks for great work! This is an effort to 
23  * break apart the various CSCF functions into logically separate
24  * components. We hope this will drive wider use. We also feel
25  * that in this way the architecture is more complete and thereby easier
26  * to manage in the Kamailio/SR environment
27  *
28  * This file is part of Kamailio, a free SIP server.
29  *
30  * Kamailio is free software; you can redistribute it and/or modify
31  * it under the terms of the GNU General Public License as published by
32  * the Free Software Foundation; either version 2 of the License, or
33  * (at your option) any later version
34  *
35  * Kamailio is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  * GNU General Public License for more details.
39  *
40  * You should have received a copy of the GNU General Public License 
41  * along with this program; if not, write to the Free Software 
42  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
43  * 
44  */
45
46 #include <stdio.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include "../../sr_module.h"
51 #include "../../events.h"
52 #include "../../dprint.h"
53 #include "../../ut.h"
54 #include "../../lib/ims/ims_getters.h"
55 #include "../tm/tm_load.h"
56 #include "../../mod_fix.h"
57 #include "../../parser/parse_uri.h"
58 #include "../../parser/parse_content.h"
59 #include "../ims_usrloc_pcscf/usrloc.h"
60 #include "../../modules/ims_dialog/dlg_load.h"
61 #include "../../modules/ims_dialog/dlg_hash.h"
62 #include "../cdp/cdp_load.h"
63 #include "../cdp_avp/mod_export.h"
64 #include "../../cfg/cfg_struct.h"
65 #include "cdpeventprocessor.h"
66 #include "rx_authdata.h"
67 #include "rx_asr.h"
68 #include "rx_str.h"
69 #include "rx_aar.h"
70 #include "mod.h"
71 #include "../../parser/sdp/sdp.h"
72
73 #include "../../lib/ims/useful_defs.h"
74 #include "ims_qos_stats.h"
75
76 MODULE_VERSION
77
78                 extern gen_lock_t* process_lock; /* lock on the process table */
79
80 str orig_session_key = str_init("originating");
81 str term_session_key = str_init("terminating");
82
83 int rx_auth_expiry = 7200;
84
85 int must_send_str = 1;
86
87 int authorize_video_flow = 1; //by default we authorize resources for video flow descriptions
88
89 struct tm_binds tmb;
90 struct cdp_binds cdpb;
91 ims_dlg_api_t dlgb;
92 bind_usrloc_t bind_usrloc;
93 cdp_avp_bind_t *cdp_avp;
94 usrloc_api_t ul;
95
96 int cdp_event_latency = 1; /*flag: report slow processing of CDP callback events or not - default enabled */
97 int cdp_event_threshold = 500; /*time in ms above which we should report slow processing of CDP callback event - default 500ms*/
98 int cdp_event_latency_loglevel = 0; /*log-level to use to report slow processing of CDP callback event - default ERROR*/
99
100 int audio_default_bandwidth = 64;
101 int video_default_bandwidth = 128;
102
103 //If set then any IP in SDP that does not match this regex then filter is added with any in flow description AVP
104 //Very useful for UEs that change ports mid way through call therefore breaking flow description filters
105 str regex_sdp_ip_prefix_to_maintain_in_fd = {0, 0};
106
107 //If set this will include an additional filter for all existing filters using the next odd port up - as this is the RTCP port
108 int include_rtcp_fd = 0;
109
110 int cdp_event_list_size_threshold = 0; /**Threshold for size of cdp event list after which a warning is logged */
111
112 stat_var *aars;
113 stat_var *strs;
114 stat_var *asrs;
115 stat_var *successful_aars;
116 stat_var *successful_strs;
117
118 static str identifier = {0, 0};
119 static int identifier_size = 0;
120
121 /** module functions */
122 static int mod_init(void);
123 static int mod_child_init(int);
124 static void mod_destroy(void);
125
126 static int fixup_aar_register(void** param, int param_no);
127 static int fixup_aar(void** param, int param_no);
128
129 int * callback_singleton; /*< Callback singleton */
130
131 int terminate_dialog_on_rx_failure = 1; //this specifies whether a dialog is torn down when a media rx session fails - in some cases you might not want the dialog torn down
132 int delete_contact_on_rx_failure = 1;  //If this is set we delete the contact if the associated signalling bearer is removed
133
134
135 str early_qosrelease_reason = {"QoS released", 12};
136 str confirmed_qosrelease_headers = {NULL, 0};
137
138
139 /* parameters storage */
140 str rx_dest_realm = str_init("ims.smilecoms.com");
141 /* Only used if we want to force the Rx peer usually this is configured at a stack level and the first request uses realm routing */
142 str rx_forced_peer = str_init("");
143
144 /* P-CSCF IP address to generate the flows for the UE<->PCSCF signaling path */
145 str af_signaling_ip = str_init("127.0.0.1");
146
147
148 /* commands wrappers and fixups */
149 static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *id, int id_type);
150 static int w_rx_aar_register(struct sip_msg *msg, char *route, char* str1, char *bar);
151
152 struct _pv_req_data {
153                 struct cell *T;
154                 struct sip_msg msg;
155                 struct sip_msg *tmsgp;
156                 unsigned int id;
157                 char *buf;
158                 int buf_size;
159 };
160
161 static struct _pv_req_data _pv_treq;
162
163 static void pv_tmx_data_init(void)
164 {
165                 memset(&_pv_treq, 0, sizeof(struct _pv_req_data));
166 }
167
168 static int pv_t_copy_msg(struct sip_msg *src, struct sip_msg *dst)
169 {
170                 dst->id = src->id;
171                 dst->rcv = src->rcv;
172                 dst->set_global_address = src->set_global_address;
173                 dst->set_global_port = src->set_global_port;
174                 dst->flags = src->flags;
175                 dst->fwd_send_flags = src->fwd_send_flags;
176                 dst->rpl_send_flags = src->rpl_send_flags;
177                 dst->force_send_socket = src->force_send_socket;
178
179                 if (parse_msg(dst->buf, dst->len, dst) != 0) {
180                                 LM_ERR("parse msg failed\n");
181                                 return -1;
182                 }
183                 return 0;
184 }
185
186
187 static cmd_export_t cmds[] = {
188                 { "Rx_AAR", (cmd_function) w_rx_aar, 4, fixup_aar, 0, REQUEST_ROUTE | ONREPLY_ROUTE},
189                 { "Rx_AAR_Register", (cmd_function) w_rx_aar_register, 2, fixup_aar_register, 0, REQUEST_ROUTE},
190                 { 0, 0, 0, 0, 0, 0}
191 };
192
193 static param_export_t params[] = {
194                 { "rx_dest_realm", PARAM_STR, &rx_dest_realm},
195                 { "rx_forced_peer", PARAM_STR, &rx_forced_peer},
196                 { "rx_auth_expiry", INT_PARAM, &rx_auth_expiry},
197                 { "af_signaling_ip", PARAM_STR, &af_signaling_ip}, /* IP of this P-CSCF, to be used in the flow for the AF-signaling */
198                 { "cdp_event_latency", INT_PARAM, &cdp_event_latency}, /*flag: report slow processing of CDP callback events or not */
199                 { "cdp_event_threshold", INT_PARAM, &cdp_event_threshold}, /*time in ms above which we should report slow processing of CDP callback event*/
200                 { "cdp_event_latency_log", INT_PARAM, &cdp_event_latency_loglevel}, /*log-level to use to report slow processing of CDP callback event*/
201                 { "authorize_video_flow", INT_PARAM, &authorize_video_flow}, /*whether or not we authorize resources for video flows*/
202                 { "cdp_event_list_size_threshold", INT_PARAM, &cdp_event_list_size_threshold}, /**Threshold for size of cdp event list after which a warning is logged */
203                 { "audio_default_bandwidth", INT_PARAM, &audio_default_bandwidth},
204                 { "video_default_bandwidth", INT_PARAM, &video_default_bandwidth},
205                 { "early_qosrelease_reason", PARAM_STR, &early_qosrelease_reason},
206                 { "confirmed_qosrelease_headers", PARAM_STR, &confirmed_qosrelease_headers},
207                 { "terminate_dialog_on_rx_failure", INT_PARAM, &terminate_dialog_on_rx_failure},
208                 { "delete_contact_on_rx_failure", INT_PARAM, &delete_contact_on_rx_failure},
209                 { "regex_sdp_ip_prefix_to_maintain_in_fd", PARAM_STR, &regex_sdp_ip_prefix_to_maintain_in_fd},
210                 { "include_rtcp_fd", INT_PARAM, &include_rtcp_fd},
211                 { 0, 0, 0}
212 };
213
214
215 /** module exports */
216 struct module_exports exports = {"ims_qos", DEFAULT_DLFLAGS, /* dlopen flags */
217                 cmds, /* Exported functions */
218                 params, 0, /* exported statistics */
219                 0, /* exported MI functions */
220                 0, /* exported pseudo-variables */
221                 0, /* extra processes */
222                 mod_init, /* module initialization function */
223                 0, mod_destroy, mod_child_init /* per-child init function */};
224
225 /**
226  * init module function
227  */
228 static int mod_init(void)
229 {
230
231                 callback_singleton = shm_malloc(sizeof(int));
232                 *callback_singleton = 0;
233
234                 /*register space for event processor*/
235                 register_procs(1);
236
237                 cdp_avp = 0;
238                 /* load the TM API */
239                 if (load_tm_api(&tmb) != 0) {
240                                 LM_ERR("can't load TM API\n");
241                                 goto error;
242                 }
243
244                 /* load the CDP API */
245                 if (load_cdp_api(&cdpb) != 0) {
246                                 LM_ERR("can't load CDP API\n");
247                                 goto error;
248                 }
249
250                 /* load the dialog API */
251                 if (load_ims_dlg_api(&dlgb) != 0) {
252                                 LM_ERR("can't load Dialog API\n");
253                                 goto error;
254                 }
255
256                 cdp_avp = load_cdp_avp();
257                 if (!cdp_avp) {
258                                 LM_ERR("can't load CDP_AVP API\n");
259                                 goto error;
260                 }
261
262                 /* load the usrloc API */
263                 bind_usrloc = (bind_usrloc_t) find_export("ul_bind_ims_usrloc_pcscf", 1, 0);
264                 if (!bind_usrloc) {
265                                 LM_ERR("can't bind usrloc_pcscf\n");
266                                 return CSCF_RETURN_FALSE;
267                 }
268
269                 if (bind_usrloc(&ul) < 0) {
270                                 LM_ERR("can't bind to usrloc pcscf\n");
271                                 return CSCF_RETURN_FALSE;
272                 }
273                 LM_DBG("Successfully bound to PCSCF Usrloc module\n");
274
275                 LM_DBG("Diameter RX interface successfully bound to TM, Dialog, Usrloc and CDP modules\n");
276
277                 /*init cdb cb event list*/
278                 if (!init_cdp_cb_event_list()) {
279                                 LM_ERR("unable to initialise cdp callback event list\n");
280                                 return -1;
281                 }
282
283                 if (ims_qos_init_counters() != 0) {
284                                 LM_ERR("Failed to register counters for ims_qos module\n");
285                                 return -1;
286                 }
287
288                 pv_tmx_data_init();
289
290                 return 0;
291 error:
292                 LM_ERR("Failed to initialise ims_qos module\n");
293                 return CSCF_RETURN_FALSE;
294 }
295
296 /**
297  * Initializes the module in child.
298  */
299 static int mod_child_init(int rank)
300 {
301                 LM_DBG("Initialization of module in child [%d] \n", rank);
302
303                 if (rank == PROC_MAIN) {
304                                 int pid = fork_process(PROC_MIN, "Rx Event Processor", 1);
305                                 if (pid < 0)
306                                                 return -1; //error
307                                 if (pid == 0) {
308                                                 if (cfg_child_init())
309                                                                 return -1; //error
310                                                 cdp_cb_event_process();
311                                 }
312                 }
313                 /* don't do anything for main process and TCP manager process */
314                 if (rank == PROC_MAIN || rank == PROC_TCP_MAIN) {
315                                 return 0;
316                 }
317
318                 lock_get(process_lock);
319                 if ((*callback_singleton) == 0) {
320                                 *callback_singleton = 1;
321                                 cdpb.AAAAddRequestHandler(callback_cdp_request, NULL);
322                 }
323                 lock_release(process_lock);
324
325                 return 0;
326 }
327
328 static void mod_destroy(void)
329 {
330                 if (identifier_size > 0 && identifier.s) {
331                                 pkg_free(identifier.s);
332                 }
333 }
334
335 /*callback of CDP session*/
336 void callback_for_cdp_session(int event, void *session)
337 {
338                 rx_authsessiondata_t* p_session_data = 0;
339                 AAASession *x = session;
340
341                 str* rx_session_id = (str*) & x->id;
342                 p_session_data = (rx_authsessiondata_t*) x->u.auth.generic_data;
343
344                 if (!rx_session_id || rx_session_id->len <= 0 || !rx_session_id->s) {
345                                 LM_ERR("Invalid Rx session id");
346                                 return;
347                 }
348
349                 if (!p_session_data) {
350                                 LM_ERR("Invalid associated session data\n");
351                                 return;
352                 }
353
354                 //only put the events we care about on the event stack
355                 if (event == AUTH_EV_SESSION_TIMEOUT ||
356                                 event == AUTH_EV_SESSION_GRACE_TIMEOUT ||
357                                 event == AUTH_EV_RECV_ASR ||
358                                 event == AUTH_EV_SERVICE_TERMINATED) {
359
360                                 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);
361
362                                 //create new event to process async
363                                 cdp_cb_event_t *new_event = new_cdp_cb_event(event, rx_session_id, p_session_data);
364                                 if (!new_event) {
365                                                 LM_ERR("Unable to create event for cdp callback\n");
366                                                 return;
367                                 }
368                                 //push the new event onto the stack (FIFO)
369                                 push_cdp_cb_event(new_event);
370                 } else {
371                                 LM_DBG("Ignoring event [%d] from CDP session\n", event);
372                 }
373 }
374
375 /**
376  * Handler for incoming Diameter requests.
377  * @param request - the received request
378  * @param param - generic pointer
379  * @returns the answer to this request
380  */
381 AAAMessage* callback_cdp_request(AAAMessage *request, void *param)
382 {
383                 if (is_req(request)) {
384
385                                 switch (request->applicationId) {
386                                 case IMS_Rx:
387                                 case IMS_Gq:
388                                                 switch (request->commandCode) {
389                                                 case IMS_RAR:
390                                                                 LM_INFO("Rx request handler():- Received an IMS_RAR \n");
391                                                                 /* TODO: Add support for Re-Auth Requests */
392                                                                 return 0;
393                                                                 break;
394                                                 case IMS_ASR:
395                                                                 LM_INFO("Rx request handler(): - Received an IMS_ASR \n");
396                                                                 return rx_process_asr(request);
397                                                                 break;
398                                                 default:
399                                                                 LM_ERR("Rx request handler(): - Received unknown request for Rx/Gq command %d, flags %#1x endtoend %u hopbyhop %u\n", request->commandCode, request->flags, request->endtoendId, request->hopbyhopId);
400                                                                 return 0;
401                                                                 break;
402                                                 }
403                                                 break;
404                                 default:
405                                                 LM_ERR("Rx request handler(): - Received unknown request for app %d command %d\n", request->applicationId, request->commandCode);
406                                                 return 0;
407                                                 break;
408                                 }
409                 }
410                 return 0;
411 }
412
413 const str match_cseq_method = {"INVITE", 6};
414
415 void callback_dialog(struct dlg_cell* dlg, int type, struct dlg_cb_params * params)
416 {
417
418                 struct sip_msg* msg = params->rpl;
419                 struct cseq_body *parsed_cseq;
420                 str *rx_session_id;
421                 rx_session_id = (str*) * params->param;
422                 AAASession *auth = 0;
423                 rx_authsessiondata_t* p_session_data = 0;
424                 flow_description_t *current_fd = 0;
425                 flow_description_t *new_fd = 0;
426                 int current_has_video = 0;
427                 int new_has_video = 0;
428                 int must_unlock_aaa = 1;
429
430                 if (rx_session_id == 0) {
431                                 LM_WARN("Strange... no rx session ID in callback.... why?\n");
432                                 return;
433                 }
434                 //getting session data
435
436                 LM_DBG("Dialog callback of type %d received\n", type);
437
438                 if (type == DLGCB_TERMINATED || type == DLGCB_DESTROY || type == DLGCB_EXPIRED || type == DLGCB_FAILED) {
439                                 LM_DBG("Dialog has ended or failed - we need to terminate Rx bearer session\n");
440
441                                 LM_DBG("Received notification of termination of dialog with Rx session ID: [%.*s]\n",
442                                                 rx_session_id->len, rx_session_id->s);
443
444                                 LM_DBG("Sending STR\n");
445                                 rx_send_str(rx_session_id);
446                 } else if (type == DLGCB_CONFIRMED) {
447
448                                 LM_DBG("Callback for confirmed dialog - copy new flow description into current flow description\n");
449                                 if (!rx_session_id || !rx_session_id->s || !rx_session_id->len) {
450                                                 LM_ERR("Dialog has no Rx session associated\n");
451                                                 goto error;
452                                 }
453
454                                 //getting auth session
455                                 auth = cdpb.AAAGetAuthSession(*rx_session_id);
456                                 if (!auth) {
457                                                 LM_DBG("Could not get Auth Session for session id: [%.*s]\n", rx_session_id->len, rx_session_id->s);
458                                                 goto error;
459                                 }
460
461                                 //getting session data
462                                 p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
463                                 if (!p_session_data) {
464                                                 LM_DBG("Could not get session data on Auth Session for session id: [%.*s]\n", rx_session_id->len, rx_session_id->s);
465                                                 goto error;
466                                 }
467
468                                 //check if there is a new flow description - if there is then free the current flow description and replace it with the new flow description
469                                 if (p_session_data->first_new_flow_description) {
470                                                 //free the current
471                                                 LM_DBG("Free-ing the current fd\n");
472                                                 free_flow_description(p_session_data, 1);
473                                                 //point the current to the new
474                                                 LM_DBG("Point the first current fd to the first new fd\n");
475                                                 p_session_data->first_current_flow_description = p_session_data->first_new_flow_description;
476                                                 //point the new to 0
477                                                 LM_DBG("Point the first new fd to 0\n");
478                                                 p_session_data->first_new_flow_description = 0;
479                                 } else {
480                                                 LM_ERR("There is no new flow description - this shouldn't happen\n");
481                                 }
482
483                                 show_callsessiondata(p_session_data);
484                                 if (auth) cdpb.AAASessionsUnlock(auth->hash);
485
486                 } else if (type == DLGCB_RESPONSE_WITHIN) {
487
488                                 LM_DBG("Dialog has received a response to a request within dialog\n");
489                                 if (!rx_session_id || !rx_session_id->s || !rx_session_id->len) {
490                                                 LM_ERR("Dialog has no Rx session associated\n");
491                                                 goto error;
492                                 }
493
494                                 //getting auth session
495                                 auth = cdpb.AAAGetAuthSession(*rx_session_id);
496                                 if (!auth) {
497                                                 LM_DBG("Could not get Auth Session for session id: [%.*s]\n", rx_session_id->len, rx_session_id->s);
498                                                 goto error;
499                                 }
500
501                                 //getting session data
502                                 p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
503
504                                 if (!p_session_data) {
505                                                 LM_DBG("Could not get session data on Auth Session for session id: [%.*s]\n", rx_session_id->len, rx_session_id->s);
506                                                 goto error;
507                                 }
508
509                                 show_callsessiondata(p_session_data);
510
511                                 if (msg->first_line.type == SIP_REPLY) {
512                                                 LM_DBG("This is a SIP REPLY\n");
513                                                 if (msg->cseq && (parsed_cseq = get_cseq(msg)) && memcmp(parsed_cseq->method.s, match_cseq_method.s, match_cseq_method.len) == 0) {
514                                                                 LM_DBG("This response has a cseq method [%.*s]\n", match_cseq_method.len, match_cseq_method.s);
515
516                                                                 if (msg->first_line.u.reply.statuscode == 200) {
517                                                                                 LM_DBG("Response is 200 - this is success\n");
518                                                                                 //check if there is a new flow description - if there is then free the current flow description and replace it with the new flow description
519                                                                                 if (p_session_data->first_new_flow_description) {
520                                                                                                 //free the current
521                                                                                                 free_flow_description(p_session_data, 1);
522                                                                                                 //point the current to the new
523                                                                                                 p_session_data->first_current_flow_description = p_session_data->first_new_flow_description;
524                                                                                                 //point the new to 0
525                                                                                                 p_session_data->first_new_flow_description = 0;
526                                                                                 } else {
527                                                                                                 LM_DBG("There is no new flow description - duplicate dialog callback - we ignore.\n");
528                                                                                 }
529                                                                 } else if (msg->first_line.u.reply.statuscode > 299) {
530                                                                                 LM_DBG("Response is more than 299 so this is an error code\n");
531
532                                                                                 new_fd = p_session_data->first_new_flow_description;
533                                                                                 //check if there is video in the new flow description
534                                                                                 while (new_fd) {
535                                                                                                 if (strncmp(new_fd->media.s, "video", 5) == 0) {
536                                                                                                                 LM_DBG("The new flow has a video fd in it\n");
537                                                                                                                 new_has_video = 1;
538
539                                                                                                 }
540                                                                                                 new_fd = new_fd->next;
541                                                                                 }
542                                                                                 //check if there is video in the current flow description
543                                                                                 current_fd = p_session_data->first_current_flow_description;
544                                                                                 while (current_fd) {
545                                                                                                 if (strncmp(current_fd->media.s, "video", 5) == 0) {
546                                                                                                                 LM_DBG("The current flow has a video fd in it\n");
547                                                                                                                 current_has_video = 1;
548
549                                                                                                 }
550                                                                                                 current_fd = current_fd->next;
551                                                                                 }
552                                                                                 if (new_has_video && !current_has_video) {
553                                                                                                 LM_DBG("New flow description has video in it, and current does not - this means we added video and it failed further upstream - "
554                                                                                                                 "so we must remove the video\n");
555                                                                                                 //We need to send AAR asynchronously with current fd
556                                                                                                 rx_send_aar_update_no_video(auth);
557                                                                                                 must_unlock_aaa = 0;
558
559                                                                                 }
560                                                                                 //free the new flow description
561                                                                                 free_flow_description(p_session_data, 0);
562                                                                 }
563                                                 }
564                                 }
565
566                                 show_callsessiondata(p_session_data);
567
568                                 if (must_unlock_aaa) {
569                                                 LM_DBG("Unlocking AAA session");
570                                                 cdpb.AAASessionsUnlock(auth->hash);
571                                 }
572                 } else {
573                                 LM_DBG("Callback type not supported - just returning");
574                 }
575
576                 return;
577
578 error:
579                 if (auth) cdpb.AAASessionsUnlock(auth->hash);
580                 return;
581 }
582
583 void callback_pcscf_contact_cb(struct pcontact *c, int type, void *param)
584 {
585                 LM_DBG("----------------------!\n");
586                 LM_DBG("PCSCF Contact Callback!\n");
587                 LM_DBG("Contact AOR: [%.*s]\n", c->aor.len, c->aor.s);
588                 LM_DBG("Callback type [%d]\n", type);
589
590
591                 if (type == PCSCF_CONTACT_EXPIRE || type == PCSCF_CONTACT_DELETE) {
592                                 //we dont need to send STR if no QoS was ever succesfully registered!
593                                 if (must_send_str && (c->reg_state != PCONTACT_REG_PENDING) && (c->reg_state != PCONTACT_REG_PENDING_AAR)) {
594                                                 LM_DBG("Received notification of contact (in state [%d] deleted for signalling bearer with  with Rx session ID: [%.*s]\n",
595                                                                 c->reg_state, c->rx_session_id.len, c->rx_session_id.s);
596                                                 LM_DBG("Sending STR\n");
597                                                 rx_send_str(&c->rx_session_id);
598                                 }
599                 }
600 }
601
602 static int get_identifier(str* src)
603 {
604                 char *sep;
605
606                 if (src == 0 || src->len == 0) {
607                                 return -1;
608                 }
609
610                 if (identifier_size <= src->len) {
611                                 if (identifier.s) {
612                                                 pkg_free(identifier.s);
613                                 }
614                                 identifier.s = (char*) pkg_malloc(src->len + 1);
615                                 if (!identifier.s) {
616                                                 LM_ERR("no more pkg mem\n");
617                                                 return -1;
618                                 }
619                                 memset(identifier.s, 0, src->len + 1);
620                                 identifier_size = src->len + 1;
621                 }
622
623                 memcpy(identifier.s, src->s, src->len);
624                 identifier.len = src->len;
625                 sep = memchr(identifier.s, 59 /* ; */, identifier.len);
626
627                 if (sep) identifier.len = (int) (sep - identifier.s);
628
629                 return 0;
630 }
631
632 uint16_t check_ip_version(str ip)
633 {
634                 struct addrinfo hint, *res = NULL;
635                 memset(&hint, '\0', sizeof(hint));
636                 hint.ai_family = AF_UNSPEC;
637                 hint.ai_flags = AI_NUMERICHOST;
638                 int getaddrret = getaddrinfo(ip.s, NULL, &hint, &res);
639                 if (getaddrret) {
640                                 LM_ERR("GetAddrInfo returned an error !\n");
641                                 return 0;
642                 }
643                 if (res->ai_family == AF_INET) {
644                                 return AF_INET;
645                 } else if (res->ai_family == AF_INET6) {
646                                 return AF_INET6;
647                 } else {
648                                 LM_ERR("unknown IP format \n");
649                                 return 0;
650                 }
651 }
652
653 /* Wrapper to send AAR from config file - this only allows for AAR for calls - not register, which uses r_rx_aar_register
654  * return: 1 - success, <=0 failure. 2 - message not a AAR generating message (ie proceed without PCC if you wish)
655  */
656 static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int id_type)
657 {
658
659                 int ret = CSCF_RETURN_ERROR;
660                 int result = CSCF_RETURN_ERROR;
661                 struct cell *t;
662                 struct sip_msg* orig_sip_request_msg = NULL;
663
664                 AAASession* auth_session = 0;
665                 rx_authsessiondata_t* rx_authdata_p = 0;
666                 str *rx_session_id = 0;
667                 str callid = {0, 0};
668                 str ftag = {0, 0};
669                 str ttag = {0, 0};
670
671                 str route_name;
672                 str ip, uri;
673                 int identifier_type;
674                 int ip_version = 0;
675                 sdp_session_cell_t* sdp_session;
676                 sdp_stream_cell_t* sdp_stream;
677                 str s_id;
678                 struct hdr_field *h = 0;
679                 struct dlg_cell* dlg = 0;
680
681                 cfg_action_t* cfg_action = 0;
682                 saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
683                 char* direction = dir;
684                 if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
685                                 LM_ERR("no async route block for assign_server_unreg\n");
686                                 return result;
687                 }
688
689                 if (get_str_fparam(&s_id, msg, (fparam_t*) c_id) < 0) {
690                                 LM_ERR("failed to get s__id\n");
691                                 return result;
692                 }
693
694                 LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
695                 int ri = route_get(&main_rt, route_name.s);
696                 if (ri < 0) {
697                                 LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
698                                 return result;
699                 }
700                 cfg_action = main_rt.rlist[ri];
701                 if (cfg_action == NULL) {
702                                 LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
703                                 return result;
704                 }
705
706                 LM_DBG("Rx AAR called\n");
707                 //create the default return code AVP
708                 create_return_code(ret);
709
710                 //We don't ever do AAR on request for calling scenario...
711                 if (msg->first_line.type != SIP_REPLY) {
712                                 LM_DBG("Can't do AAR for call session in request\n");
713                                 return result;
714                 }
715
716                 //is it appropriate to send AAR at this stage?
717                 t = tmb.t_gett();
718                 if (t == NULL || t == T_UNDEFINED) {
719                                 LM_WARN("Cannot get transaction for AAR based on SIP Request\n");
720                                 //goto aarna;
721                                 return result;
722                 }
723
724                 if (t->uas.status >= 200) {
725                                 LM_DBG("trasaction sent out a final response already - %d\n",
726                                                 t->uas.status);
727                                 return result;
728                 }
729
730
731                 /*  we may need the request message from here on.. if there are headers we need that were not parsed in the original request
732                         (which we cannot assume) then we would pollute the shm_msg t->uas.request if we did any parsing on it. Instead, we need to 
733                         make a private copy of the message and free it when we are done 
734                  */
735                 if ((_pv_treq.T != t || t->uas.request != _pv_treq.tmsgp)
736                                 && t->uas.request->id != _pv_treq.id) {
737
738                                 /* make a copy */
739                                 if (_pv_treq.buf == NULL || _pv_treq.buf_size < t->uas.request->len + 1) {
740                                                 if (_pv_treq.buf != NULL)
741                                                                 pkg_free(_pv_treq.buf);
742                                                 if (_pv_treq.tmsgp)
743                                                                 free_sip_msg(&_pv_treq.msg);
744                                                 _pv_treq.tmsgp = NULL;
745                                                 _pv_treq.id = 0;
746                                                 _pv_treq.T = NULL;
747                                                 _pv_treq.buf_size = t->uas.request->len + 1;
748                                                 _pv_treq.buf = (char*) pkg_malloc(_pv_treq.buf_size * sizeof(char));
749                                                 if (_pv_treq.buf == NULL) {
750                                                                 LM_ERR("no more pkg\n");
751                                                                 _pv_treq.buf_size = 0;
752                                                                 return -1;
753                                                 }
754                                 }
755                                 if (_pv_treq.tmsgp)
756                                                 free_sip_msg(&_pv_treq.msg);
757                                 memset(&_pv_treq.msg, 0, sizeof(struct sip_msg));
758                                 memcpy(_pv_treq.buf, t->uas.request->buf, t->uas.request->len);
759                                 _pv_treq.buf[t->uas.request->len] = '\0';
760                                 _pv_treq.msg.len = t->uas.request->len;
761                                 _pv_treq.msg.buf = _pv_treq.buf;
762                                 _pv_treq.tmsgp = t->uas.request;
763                                 _pv_treq.id = t->uas.request->id;
764                                 _pv_treq.T = t;
765
766
767                                 if (pv_t_copy_msg(t->uas.request, &_pv_treq.msg) != 0) {
768                                                 pkg_free(_pv_treq.buf);
769                                                 _pv_treq.buf_size = 0;
770                                                 _pv_treq.buf = NULL;
771                                                 _pv_treq.tmsgp = NULL;
772                                                 _pv_treq.T = NULL;
773                                                 return -1;
774                                 }
775                 }
776
777                 orig_sip_request_msg = &_pv_treq.msg;
778
779
780                 //we dont apply QoS if its not a reply to an INVITE! or UPDATE or PRACK!
781                 if ((t->method.len == 5 && memcmp(t->method.s, "PRACK", 5) == 0)
782                                 || (t->method.len == 6 && (memcmp(t->method.s, "INVITE", 6) == 0
783                                 || memcmp(t->method.s, "UPDATE", 6) == 0))) {
784                                 if (cscf_get_content_length(msg) == 0
785                                                 || cscf_get_content_length(orig_sip_request_msg) == 0) {
786                                                 LM_DBG("No SDP offer answer -> therefore we can not do Rx AAR");
787                                                 //goto aarna; //AAR na if we dont have offer/answer pair
788                                                 return result;
789                                 }
790                 } else {
791                                 LM_DBG("Message is not response to INVITE, PRACK or UPDATE -> therefore we do not Rx AAR");
792                                 return result;
793                 }
794
795                 /* get callid, from and to tags to be able to identify dialog */
796                 callid = cscf_get_call_id(msg, 0);
797                 if (callid.len <= 0 || !callid.s) {
798                                 LM_ERR("unable to get callid\n");
799                                 return result;
800                 }
801                 if (!cscf_get_from_tag(msg, &ftag)) {
802                                 LM_ERR("Unable to get ftag\n");
803                                 return result;
804                 }
805                 if (!cscf_get_to_tag(msg, &ttag)) {
806                                 LM_ERR("Unable to get ttag\n");
807                                 return result;
808                 }
809
810                 //check to see that this is not a result of a retransmission in reply route only
811                 if (msg->cseq == NULL
812                                 && ((parse_headers(msg, HDR_CSEQ_F, 0) == -1) || (msg->cseq == NULL))) {
813                                 LM_ERR("No Cseq header found - aborting\n");
814                                 return result;
815                 }
816
817                 saved_t_data = (saved_transaction_t*) shm_malloc(sizeof(saved_transaction_t));
818                 if (!saved_t_data) {
819                                 LM_ERR("Unable to allocate memory for transaction data, trying to send AAR\n");
820                                 return result;
821                 }
822                 memset(saved_t_data, 0, sizeof(saved_transaction_t));
823                 saved_t_data->act = cfg_action;
824                 //OTHER parms need after async response set here
825                 //store call id
826                 saved_t_data->callid.s = (char*) shm_malloc(callid.len + 1);
827                 if (!saved_t_data->callid.s) {
828                                 LM_ERR("no more memory trying to save transaction state : callid\n");
829                                 shm_free(saved_t_data);
830                                 return result;
831                 }
832                 memset(saved_t_data->callid.s, 0, callid.len + 1);
833                 memcpy(saved_t_data->callid.s, callid.s, callid.len);
834                 saved_t_data->callid.len = callid.len;
835
836                 //store ttag
837                 saved_t_data->ttag.s = (char*) shm_malloc(ttag.len + 1);
838                 if (!saved_t_data->ttag.s) {
839                                 LM_ERR("no more memory trying to save transaction state : ttag\n");
840                                 shm_free(saved_t_data);
841                                 return result;
842                 }
843                 memset(saved_t_data->ttag.s, 0, ttag.len + 1);
844                 memcpy(saved_t_data->ttag.s, ttag.s, ttag.len);
845                 saved_t_data->ttag.len = ttag.len;
846
847                 //store ftag
848                 saved_t_data->ftag.s = (char*) shm_malloc(ftag.len + 1);
849                 if (!saved_t_data->ftag.s) {
850                                 LM_ERR("no more memory trying to save transaction state : ftag\n");
851                                 shm_free(saved_t_data);
852                                 return result;
853                 }
854                 memset(saved_t_data->ftag.s, 0, ftag.len + 1);
855                 memcpy(saved_t_data->ftag.s, ftag.s, ftag.len);
856                 saved_t_data->ftag.len = ftag.len;
857
858                 saved_t_data->aar_update = 0; //by default we say this is not an aar update - if it is we set it below
859
860                 //store branch
861                 int branch;
862                 if (tmb.t_check(msg, &branch) == -1) {
863                                 LOG(L_ERR, "ERROR: t_suspend: failed find UAC branch\n");
864                                 return result;
865                 }
866
867                 //Check that we dont already have an auth session for this specific dialog
868                 //if not we create a new one and attach it to the dialog (via session ID).
869                 enum dialog_direction dlg_direction = get_dialog_direction(direction);
870                 if (dlg_direction == DLG_MOBILE_ORIGINATING) {
871                                 rx_session_id = dlgb.get_dlg_var(&callid, &ftag, &ttag,
872                                                 &orig_session_key);
873                 } else {
874                                 rx_session_id = dlgb.get_dlg_var(&callid, &ftag, &ttag,
875                                                 &term_session_key);
876                 }
877                 if (rx_session_id && rx_session_id->len > 0 && rx_session_id->s) {
878                                 auth_session = cdpb.AAAGetAuthSession(*rx_session_id);
879                                 if (auth_session && auth_session->u.auth.state != AUTH_ST_OPEN) {
880                                                 LM_DBG("This session is not state open - so we will create a new session");
881                                                 if (auth_session) cdpb.AAASessionsUnlock(auth_session->hash);
882                                                 auth_session = 0;
883                                 }
884                 }
885
886                 if (!auth_session) {
887                                 LM_DBG("New AAR session for this dialog in mode %s\n", direction);
888
889
890                                 //get ip and subscription_id and store them in the call session data
891
892                                 //SUBSCRIPTION-ID
893
894                                 //if subscription-id and identifier_type is passed from config file we use them - if not we use default behaviour of
895
896                                 //if its mo we use p_asserted_identity in request - if that not there we use from_uri
897                                 //if its mt we use p_asserted_identity in reply - if that not there we use to_uri
898                                 if (s_id.len > 0 && id_type > -1) {
899                                                 get_identifier(&s_id);
900                                                 identifier_type = id_type;
901                                                 LM_DBG("Passed in subscription_id [%.*s] and subscription_id_type [%d]\n", identifier.len, identifier.s, identifier_type);
902                                 } else {
903                                                 if (dlg_direction == DLG_MOBILE_ORIGINATING) {
904                                                                 LM_DBG("originating direction\n");
905                                                                 uri = cscf_get_asserted_identity(orig_sip_request_msg, 0);
906                                                                 if (uri.len == 0) {
907                                                                                 LM_ERR("No P-Asserted-Identity hdr found in request. Using From hdr in req - we shouldn't have to do this");
908
909                                                                                 if (!cscf_get_from_uri(orig_sip_request_msg, &uri)) {
910                                                                                                 LM_ERR("Error assigning P-Asserted-Identity using From hdr in req");
911                                                                                                 goto error;
912                                                                                 }
913                                                                                 LM_DBG("going to remove parameters if any from identity: [%.*s]\n", uri.len, uri.s);
914                                                                                 get_identifier(&uri);
915                                                                                 LM_DBG("identifier from uri : [%.*s]\n", identifier.len, identifier.s);
916
917                                                                 } else {
918                                                                                 get_identifier(&uri);
919                                                                                 //free this cscf_get_asserted_identity allocates it
920                                                                                 //                    pkg_free(uri.s);
921                                                                 }
922                                                 } else {
923                                                                 LM_DBG("terminating direction\n");
924                                                                 uri = cscf_get_asserted_identity(msg, 0);
925                                                                 if (uri.len == 0) {
926                                                                                 LM_DBG("No P-Asserted-Identity hdr found in response. Using Called party id in resp");
927                                                                                 //get identity from called party id
928                                                                                 //getting called asserted identity
929                                                                                 uri = cscf_get_public_identity_from_called_party_id(orig_sip_request_msg, &h);
930                                                                                 if (uri.len == 0) {
931                                                                                                 LM_ERR("No P-Called-Party hdr found in response. Using req URI from dlg - we shouldn't have to do this");
932                                                                                                 //get dialog and get the req URI from there
933                                                                                                 dlg = dlgb.get_dlg(msg);
934                                                                                                 if (!dlg) {
935                                                                                                                 LM_ERR("Unable to find dialog and cannot do Rx without it\n");
936                                                                                                                 goto error;
937                                                                                                 }
938                                                                                                 LM_DBG("dlg req uri : [%.*s] going to remove parameters if any\n", dlg->req_uri.len, dlg->req_uri.s);
939
940                                                                                                 if (get_identifier(&dlg->req_uri) != 0) {
941                                                                                                                 dlgb.release_dlg(dlg);
942                                                                                                                 goto error;
943                                                                                                 }
944                                                                                                 dlgb.release_dlg(dlg);
945                                                                                                 LM_DBG("identifier from dlg req uri : [%.*s]\n", identifier.len, identifier.s);
946                                                                                 } else {
947                                                                                                 get_identifier(&uri);
948                                                                                 }
949                                                                 } else {
950                                                                                 get_identifier(&uri);
951                                                                 }
952                                                 }
953                                                 if (strncasecmp(identifier.s, "tel:", 4) == 0) {
954                                                                 identifier_type = AVP_Subscription_Id_Type_E164; //
955                                                 } else {
956                                                                 identifier_type = AVP_Subscription_Id_Type_SIP_URI; //default is END_USER_SIP_URI
957                                                 }
958                                 }
959                                 //IP 
960                                 //if its mo we use request SDP
961                                 //if its mt we use reply SDP
962                                 if (dlg_direction == DLG_MOBILE_ORIGINATING) {
963                                                 LM_DBG("originating direction\n");
964                                                 //get ip from request sdp (we use first SDP session)
965                                                 if (parse_sdp(orig_sip_request_msg) < 0) {
966                                                                 LM_ERR("Unable to parse req SDP\n");
967                                                                 goto error;
968                                                 }
969
970                                                 sdp_session = get_sdp_session(orig_sip_request_msg, 0);
971                                                 if (!sdp_session) {
972                                                                 LM_ERR("Missing SDP session information from req\n");
973                                                                 goto error;
974                                                 }
975                                                 ip = sdp_session->ip_addr;
976                                                 ip_version = sdp_session->pf;
977                                                 
978                                                 LM_DBG("IP retrieved from Request SDP to use for framed IP address: [%.*s]", ip.len, ip.s);
979                                                 
980                                                 if (ip.len <= 0) {
981                                                                 LM_DBG("Request SDP connection IP could not be retrieved, so we use SDP stream IP");
982                                                                 sdp_stream = get_sdp_stream(orig_sip_request_msg, 0, 0);
983                                                                 if (!sdp_stream) {
984                                                                                 LM_ERR("Missing SDP stream information from request\n");
985                                                                                 goto error;
986                                                                 }
987                                                                 
988                                                                 ip = sdp_stream->ip_addr;
989                                                                 if (ip.len <= 0) {
990                                                                                 LM_ERR("Request SDP IP information could not be retrieved");
991                                                                                 goto error;
992                                                                 }
993                                                                 ip_version = check_ip_version(ip);
994                                                                 if (!ip_version) {
995                                                                                 LM_ERR("check_ip_version returned 0 \n");
996                                                                                 goto error;
997                                                                 }
998                                                                 
999                                                 }
1000                                                 
1001                                                 free_sdp((sdp_info_t**) (void*) &t->uas.request->body);
1002                                                 
1003                                 } else {
1004                                                 LM_DBG("terminating direction\n");
1005                                                 //get ip from reply sdp (we use first SDP session)
1006                                                 if (parse_sdp(msg) < 0) {
1007                                                                 LM_ERR("Unable to parse reply SDP\n");
1008                                                                 goto error;
1009                                                 }
1010
1011                                                 sdp_session = get_sdp_session(msg, 0);
1012                                                 if (!sdp_session) {
1013                                                                 LM_ERR("Missing SDP session information from reply\n");
1014                                                                 goto error;
1015                                                 }
1016                                                 ip = sdp_session->ip_addr;
1017                                                 ip_version = sdp_session->pf;
1018                                                 
1019                                                 LM_DBG("IP retrieved from Reply SDP to use for framed IP address: [%.*s]", ip.len, ip.s);
1020                                                 
1021                                                 if (ip.len <= 0) {
1022                                                                 LM_DBG("Reply SDP connection IP could not be retrieved, so we use SDP stream IP");
1023                                                                 sdp_stream = get_sdp_stream(msg, 0, 0);
1024                                                                 if (!sdp_stream) {
1025                                                                                 LM_ERR("Missing SDP stream information from reply\n");
1026                                                                                 goto error;
1027                                                                 }
1028                                                                 
1029                                                                 ip = sdp_stream->ip_addr;
1030                                                                 if (ip.len <= 0) {
1031                                                                                 LM_ERR("Reply SDP IP information could not be retrieved");
1032                                                                                 goto error;
1033                                                                 }
1034                                                                 ip_version = check_ip_version(ip);
1035                                                                 if (!ip_version) {
1036                                                                                 LM_ERR("check_ip_version returned 0 \n");
1037                                                                                 goto error;
1038                                                                 }
1039                                                                 
1040                                                 }
1041                                                 
1042                                                 free_sdp((sdp_info_t**) (void*) &msg->body);
1043                                 }
1044
1045                                 int ret = create_new_callsessiondata(&callid, &ftag, &ttag, &identifier, identifier_type, &ip, ip_version, &rx_authdata_p);
1046                                 if (!ret) {
1047                                                 LM_DBG("Unable to create new media session data parcel\n");
1048                                                 goto error;
1049                                 }
1050
1051                                 //create new diameter auth session
1052                                 auth_session = cdpb.AAACreateClientAuthSession(1, callback_for_cdp_session, rx_authdata_p); //returns with a lock
1053                                 if (!auth_session) {
1054                                                 LM_ERR("Rx: unable to create new Rx Media Session\n");
1055                                                 if (auth_session) cdpb.AAASessionsUnlock(auth_session->hash);
1056                                                 if (rx_authdata_p) {
1057                                                                 free_callsessiondata(rx_authdata_p);
1058                                                 }
1059                                                 goto error;
1060                                 }
1061                                 auth_session->u.auth.class = AUTH_CLASS_RXMEDIA;
1062
1063                                 //attach new cdp auth session to dlg for this direction
1064                                 if (dlg_direction == DLG_MOBILE_ORIGINATING) {
1065                                                 dlgb.set_dlg_var(&callid, &ftag, &ttag,
1066                                                                 &orig_session_key, &auth_session->id);
1067                                 } else {
1068                                                 dlgb.set_dlg_var(&callid, &ftag, &ttag,
1069                                                                 &term_session_key, &auth_session->id);
1070                                 }
1071                                 LM_DBG("Attached CDP auth session [%.*s] for Rx to dialog in %s mode\n", auth_session->id.len, auth_session->id.s, direction);
1072                 } else {
1073                                 LM_DBG("Update AAR session for this dialog in mode %s\n", direction);
1074                                 //check if this is triggered by a 183 - if so break here as its probably a re-transmit
1075                                 if ((msg->first_line).u.reply.statuscode == 183) {
1076                                                 LM_DBG("Received a 183 for a diameter session that already exists - just going to ignore this\n");
1077                                                 cdpb.AAASessionsUnlock(auth_session->hash);
1078                                                 result = CSCF_RETURN_TRUE;
1079                                                 goto ignore;
1080                                 }
1081                                 saved_t_data->aar_update = 1; //this is an update aar - we set this so on async_aar we know this is an update and act accordingly
1082                 }
1083
1084                 LM_DBG("Suspending SIP TM transaction\n");
1085                 if (tmb.t_suspend(msg, &saved_t_data->tindex, &saved_t_data->tlabel) != 0) {
1086                                 LM_ERR("failed to suspend the TM processing\n");
1087                                 if (auth_session) cdpb.AAASessionsUnlock(auth_session->hash);
1088                                 goto error;
1089                 }
1090
1091                 LM_DBG("Sending Rx AAR");
1092                 ret = rx_send_aar(orig_sip_request_msg, msg, auth_session, direction, saved_t_data);
1093
1094                 if (!ret) {
1095                                 LM_ERR("Failed to send AAR\n");
1096                                 tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
1097                                 goto error;
1098
1099
1100                 } else {
1101                                 LM_DBG("Successful async send of AAR\n");
1102                                 result = CSCF_RETURN_BREAK;
1103                                 return result; //on success we break - because rest of cfg file will be executed by async process
1104                 }
1105
1106 error:
1107                 LM_ERR("Error trying to send AAR (calling)\n");
1108                 if (auth_session != NULL) {
1109                                 cdpb.AAASessionsUnlock(auth_session->hash);
1110                                 cdpb.AAADropAuthSession(auth_session);
1111                 }
1112 ignore:
1113                 if (saved_t_data)
1114                                 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
1115                 //otherwise the callback will segfault
1116                 return result;
1117 }
1118
1119 /* Wrapper to send AAR from config file - only used for registration */
1120 static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char* bar)
1121 {
1122
1123                 int ret = CSCF_RETURN_ERROR;
1124                 struct pcontact_info ci;
1125                 struct cell *t;
1126                 contact_t* c;
1127                 struct hdr_field* h;
1128                 pcontact_t* pcontact;
1129                 pcontact_info_t contact_info;
1130                 contact_body_t* cb = 0;
1131                 AAASession* auth;
1132                 rx_authsessiondata_t* rx_regsession_data_p;
1133                 cfg_action_t* cfg_action = 0;
1134                 str route_name;
1135                 char* p;
1136                 int aar_sent = 0;
1137                 saved_transaction_local_t* local_data = 0; //data to be shared across all async calls
1138                 saved_transaction_t* saved_t_data = 0; //data specific to each contact's AAR async call
1139                 str recv_ip;
1140                 int recv_port;
1141                 unsigned short recv_proto;
1142                 uint16_t ip_version;
1143
1144                 struct via_body* vb;
1145                 unsigned short via_port;
1146                 unsigned short via_proto;
1147
1148                 if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
1149                                 LM_ERR("no async route block for assign_server_unreg\n");
1150                                 return -1;
1151                 }
1152
1153                 LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
1154                 int ri = route_get(&main_rt, route_name.s);
1155                 if (ri < 0) {
1156                                 LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
1157                                 return -1;
1158                 }
1159                 cfg_action = main_rt.rlist[ri];
1160                 if (cfg_action == NULL) {
1161                                 LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
1162                                 return -1;
1163                 }
1164
1165                 udomain_t* domain_t = (udomain_t*) str1;
1166
1167                 int is_rereg = 0; //is this a reg/re-reg
1168
1169                 LM_DBG("Rx AAR Register called\n");
1170
1171                 //create the default return code AVP
1172                 create_return_code(ret);
1173
1174                 memset(&ci, 0, sizeof(struct pcontact_info));
1175
1176                 /** If this is a response then let's check the status before we try and do an AAR.
1177                  * We will only do AAR for register on success response and of course if message is register
1178                  */
1179                 if (msg->first_line.type == SIP_REPLY) {
1180                                 //check this is a response to a register
1181                                 /* Get the SIP request from this transaction */
1182                                 t = tmb.t_gett();
1183                                 if (!t) {
1184                                                 LM_ERR("Cannot get transaction for AAR based on SIP Request\n");
1185                                                 goto error;
1186                                 }
1187                                 if ((strncmp(t->method.s, "REGISTER", 8) != 0)) {
1188                                                 LM_ERR("Method is not a response to a REGISTER\n");
1189                                                 goto error;
1190                                 }
1191                                 if (msg->first_line.u.reply.statuscode < 200
1192                                                 || msg->first_line.u.reply.statuscode >= 300) {
1193                                                 LM_DBG("Message is not a 2xx OK response to a REGISTER\n");
1194                                                 goto error;
1195                                 }
1196                                 tmb.t_release(msg);
1197                 } else { //SIP Request
1198                                 /* in case of request make sure it is a REGISTER */
1199                                 if (msg->first_line.u.request.method_value != METHOD_REGISTER) {
1200                                                 LM_DBG("This is not a register request\n");
1201                                                 goto error;
1202                                 }
1203
1204                                 if ((cscf_get_max_expires(msg, 0) == 0)) {
1205                                                 //if ((cscf_get_expires(msg) == 0)) {
1206                                                 LM_DBG("This is a de registration\n");
1207                                                 LM_DBG("We ignore it as these are dealt with by usrloc callbacks \n");
1208                                                 create_return_code(CSCF_RETURN_TRUE);
1209                                                 return CSCF_RETURN_TRUE;
1210                                 }
1211                 }
1212
1213                 vb = cscf_get_ue_via(msg);
1214                 via_port = vb->port ? vb->port : 5060;
1215                 via_proto = vb->proto;
1216
1217                 //before we continue, make sure we have a transaction to work with (viz. cdp async)
1218                 t = tmb.t_gett();
1219                 if (t == NULL || t == T_UNDEFINED) {
1220                                 if (tmb.t_newtran(msg) < 0) {
1221                                                 LM_ERR("cannot create the transaction for UAR async\n");
1222                                                 return CSCF_RETURN_ERROR;
1223                                 }
1224                                 t = tmb.t_gett();
1225                                 if (t == NULL || t == T_UNDEFINED) {
1226                                                 LM_ERR("cannot lookup the transaction\n");
1227                                                 return CSCF_RETURN_ERROR;
1228                                 }
1229                 }
1230
1231                 saved_t_data = (saved_transaction_t*) shm_malloc(sizeof(saved_transaction_t));
1232                 if (!saved_t_data) {
1233                                 LM_ERR("Unable to allocate memory for transaction data, trying to send AAR\n");
1234                                 return CSCF_RETURN_ERROR;
1235                 }
1236                 memset(saved_t_data, 0, sizeof(saved_transaction_t));
1237                 saved_t_data->act = cfg_action;
1238                 saved_t_data->domain = domain_t;
1239                 saved_t_data->lock = lock_alloc();
1240                 if (saved_t_data->lock == NULL) {
1241                                 LM_ERR("unable to allocate init lock for saved_t_transaction reply counter\n");
1242                                 return CSCF_RETURN_ERROR;
1243                 }
1244                 if (lock_init(saved_t_data->lock) == NULL) {
1245                                 LM_ERR("unable to init lock for saved_t_transaction reply counter\n");
1246                                 return CSCF_RETURN_ERROR;
1247                 }
1248
1249                 LM_DBG("Suspending SIP TM transaction\n");
1250                 if (tmb.t_suspend(msg, &saved_t_data->tindex, &saved_t_data->tlabel) != 0) {
1251                                 LM_ERR("failed to suspend the TM processing\n");
1252                                 free_saved_transaction_global_data(saved_t_data);
1253                                 return CSCF_RETURN_ERROR;
1254                 }
1255
1256                 LM_DBG("Successfully suspended transaction\n");
1257
1258                 //now get the contacts in the REGISTER and do AAR for each one.
1259                 cb = cscf_parse_contacts(msg);
1260                 if (!cb || (!cb->contacts && !cb->star)) {
1261                                 LM_DBG("No contact headers in Register message\n");
1262                                 goto error;
1263                 }
1264
1265                 //we use the received IP address for the framed_ip_address 
1266                 recv_ip.s = ip_addr2a(&msg->rcv.src_ip);
1267                 recv_ip.len = strlen(ip_addr2a(&msg->rcv.src_ip));
1268
1269                 ip_version = check_ip_version(recv_ip);
1270                 if (!ip_version) {
1271                                 LM_ERR("check_ip_version returned 0 \n");
1272                                 goto error;
1273                 }
1274
1275                 recv_port = msg->rcv.src_port;
1276                 recv_proto = msg->rcv.proto;
1277
1278                 LM_DBG("Message received IP address is: [%.*s]\n", recv_ip.len, recv_ip.s);
1279                 LM_DBG("Message via is [%d://%.*s:%d]\n", vb->proto, vb->host.len, vb->host.s, via_port);
1280
1281                 lock_get(saved_t_data->lock); //we lock here to make sure we send all requests before processing replies asynchronously
1282                 for (h = msg->contact; h; h = h->next) {
1283                                 if (h->type == HDR_CONTACT_T && h->parsed) {
1284                                                 for (c = ((contact_body_t*) h->parsed)->contacts; c; c = c->next) {
1285                                                                 ul.lock_udomain(domain_t, &vb->host, vb->port, vb->proto);
1286                                                                 memset(&contact_info, 0, sizeof(struct pcontact_info));
1287                                                                 contact_info.aor = c->uri;
1288                                                                 contact_info.via_host = vb->host;
1289                                                                 contact_info.via_port = vb->port;
1290                                                                 contact_info.via_prot = vb->proto;
1291                                                                 contact_info.searchflag = SEARCH_NORMAL;
1292                                                                 contact_info.received_host.s = 0;
1293                                                                 contact_info.received_host.len = 0;
1294                                                                 contact_info.reg_state = PCONTACT_ANY; //search for any state
1295
1296                                                                 if (ul.get_pcontact(domain_t, &contact_info, &pcontact) != 0) {
1297                                                                                 LM_ERR("This contact does not exist in PCSCF usrloc - error in cfg file\n");
1298                                                                                 ul.unlock_udomain(domain_t, &vb->host, vb->port, vb->proto);
1299                                                                                 lock_release(saved_t_data->lock);
1300                                                                                 goto error;
1301                                                                 } else if (pcontact->reg_state == PCONTACT_REG_PENDING
1302                                                                                 || pcontact->reg_state == PCONTACT_REGISTERED) { //NEW reg request
1303                                                                                 LM_DBG("Contact [%.*s] exists and is in state PCONTACT_REG_PENDING or PCONTACT_REGISTERED\n"
1304                                                                                                 , pcontact->aor.len, pcontact->aor.s);
1305
1306                                                                                 //check for existing Rx session
1307                                                                                 if (pcontact->rx_session_id.len > 0
1308                                                                                                 && pcontact->rx_session_id.s
1309                                                                                                 && (auth = cdpb.AAAGetAuthSession(pcontact->rx_session_id))) {
1310                                                                                                 LM_DBG("Rx session already exists for this user\n");
1311                                                                                                 if (memcmp(pcontact->rx_session_id.s, auth->id.s, auth->id.len) != 0) {
1312                                                                                                                 LM_ERR("Rx session mismatch for rx_session_id [%.*s].......Aborting\n", pcontact->rx_session_id.len, pcontact->rx_session_id.s);
1313                                                                                                                 if (auth) cdpb.AAASessionsUnlock(auth->hash);
1314                                                                                                                 lock_release(saved_t_data->lock);
1315                                                                                                                 goto error;
1316                                                                                                 }
1317                                                                                                 //re-registration - update auth lifetime
1318                                                                                                 auth->u.auth.lifetime = time(NULL) + rx_auth_expiry;
1319                                                                                                 is_rereg = 1;
1320                                                                                 } else {
1321                                                                                                 LM_DBG("Creating new Rx session for contact <%.*s>\n", pcontact->aor.len, pcontact->aor.s);
1322                                                                                                 int ret = create_new_regsessiondata(domain_t->name, &pcontact->aor, &recv_ip, ip_version, recv_port, recv_proto, &vb->host, vb->port, vb->proto, &rx_regsession_data_p);
1323                                                                                                 if (!ret) {
1324                                                                                                                 LM_ERR("Unable to create regsession data parcel for rx_session_id [%.*s]...Aborting\n", pcontact->rx_session_id.len, pcontact->rx_session_id.s);
1325                                                                                                                 ul.unlock_udomain(domain_t, &vb->host, vb->port, vb->proto);
1326                                                                                                                 if (rx_regsession_data_p) {
1327                                                                                                                                 shm_free(rx_regsession_data_p);
1328                                                                                                                                 rx_regsession_data_p = 0;
1329                                                                                                                 }
1330                                                                                                                 lock_release(saved_t_data->lock);
1331                                                                                                                 goto error;
1332                                                                                                 }
1333                                                                                                 auth = cdpb.AAACreateClientAuthSession(1, callback_for_cdp_session, rx_regsession_data_p); //returns with a lock
1334                                                                                                 if (!auth) {
1335                                                                                                                 LM_ERR("Rx: unable to create new Rx Reg Session for rx_session_id is [%.*s]\n", pcontact->rx_session_id.len, pcontact->rx_session_id.s);
1336                                                                                                                 if (rx_regsession_data_p) {
1337                                                                                                                                 shm_free(rx_regsession_data_p);
1338                                                                                                                                 rx_regsession_data_p = 0;
1339                                                                                                                 }
1340                                                                                                                 ul.unlock_udomain(domain_t, &vb->host, via_port, via_proto);
1341                                                                                                                 if (auth) cdpb.AAASessionsUnlock(auth->hash);
1342                                                                                                                 if (rx_regsession_data_p) {
1343                                                                                                                                 shm_free(rx_regsession_data_p);
1344                                                                                                                                 rx_regsession_data_p = 0;
1345                                                                                                                 }
1346                                                                                                                 lock_release(saved_t_data->lock);
1347                                                                                                                 goto error;
1348                                                                                                 }
1349                                                                                                 auth->u.auth.class = AUTH_CLASS_RXREG;
1350                                                                                 }
1351
1352                                                                                 //we are ready to send the AAR async. lets save the local data data
1353                                                                                 int local_data_len = sizeof(saved_transaction_local_t) + c->uri.len + auth->id.len + vb->host.len + recv_ip.len;
1354                                                                                 local_data = shm_malloc(local_data_len);
1355                                                                                 if (!local_data) {
1356                                                                                                 LM_ERR("unable to alloc memory for local data, trying to send AAR Register\n");
1357                                                                                                 lock_release(saved_t_data->lock);
1358                                                                                                 goto error;
1359                                                                                 }
1360                                                                                 memset(local_data, 0, local_data_len);
1361
1362                                                                                 local_data->is_rereg = is_rereg;
1363                                                                                 local_data->global_data = saved_t_data;
1364                                                                                 p = (char*) (local_data + 1);
1365
1366                                                                                 local_data->contact.s = p;
1367                                                                                 local_data->contact.len = c->uri.len;
1368                                                                                 memcpy(p, c->uri.s, c->uri.len);
1369                                                                                 p += c->uri.len;
1370
1371                                                                                 local_data->auth_session_id.s = p;
1372                                                                                 local_data->auth_session_id.len = auth->id.len;
1373                                                                                 memcpy(p, auth->id.s, auth->id.len);
1374                                                                                 p += auth->id.len;
1375
1376                                                                                 local_data->via_host.s = p;
1377                                                                                 local_data->via_host.len = vb->host.len;
1378                                                                                 memcpy(p, vb->host.s, vb->host.len);
1379                                                                                 p += vb->host.len;
1380
1381                                                                                 local_data->recv_host.s = p;
1382                                                                                 local_data->recv_host.len = recv_ip.len;
1383                                                                                 memcpy(p, recv_ip.s, recv_ip.len);
1384                                                                                 p += recv_ip.len;
1385
1386                                                                                 local_data->via_port = via_port;
1387                                                                                 local_data->via_proto = via_proto;
1388                                                                                 local_data->recv_port = recv_port;
1389                                                                                 local_data->recv_proto = recv_proto;
1390
1391                                                                                 if (p != (((char*) local_data) + local_data_len)) {
1392                                                                                                 LM_CRIT("buffer overflow\n");
1393                                                                                                 free_saved_transaction_data(local_data);
1394                                                                                                 goto error;
1395                                                                                 }
1396
1397                                                                                 LM_DBG("Calling send aar register");
1398
1399                                                                                 //TODOD remove - no longer user AOR parm
1400                                                                                 //ret = rx_send_aar_register(msg, auth, &puri.host, &ip_version, &c->uri, local_data); //returns a locked rx auth object
1401                                                                                 ret = rx_send_aar_register(msg, auth, local_data); //returns a locked rx auth object
1402
1403                                                                                 ul.unlock_udomain(domain_t, &vb->host, via_port, via_proto);
1404
1405                                                                                 if (!ret) {
1406                                                                                                 LM_ERR("Failed to send AAR\n");
1407                                                                                                 lock_release(saved_t_data->lock);
1408                                                                                                 free_saved_transaction_data(local_data); //free the local data becuase the CDP async request was not successful (we must free here)
1409                                                                                                 goto error;
1410                                                                                 } else {
1411                                                                                                 aar_sent = 1;
1412                                                                                                 //before we send - bump up the reply counter
1413                                                                                                 saved_t_data->answers_not_received++; //we dont need to lock as we already hold the lock above
1414                                                                                 }
1415                                                                 } else {
1416                                                                                 //contact exists - this is a re-registration, for now we just ignore this
1417                                                                                 LM_DBG("This contact exists and is not in state REGISTER PENDING - we assume re (or de) registration and ignore\n");
1418                                                                                 ul.unlock_udomain(domain_t, &vb->host, via_port, via_proto);
1419                                                                                 //now we loop for any other contacts.
1420                                                                 }
1421                                                 }
1422                                 } else {
1423                                                 if (h->type == HDR_CONTACT_T) { //means we couldnt parse the contact - this is an error
1424                                                                 LM_ERR("Failed to parse contact header\n");
1425                                                                 lock_release(saved_t_data->lock);
1426                                                                 goto error;
1427                                                 }
1428                                 }
1429                 }
1430                 //all requests sent at this point - we can unlock the reply lock
1431                 lock_release(saved_t_data->lock);
1432
1433                 /*if we get here, we have either:
1434                  * 1. Successfully sent AAR's for ALL contacts, or
1435                  * 2. haven't needed to send ANY AAR's for ANY contacts
1436                  */
1437                 if (aar_sent) {
1438                                 LM_DBG("Successful async send of AAR\n");
1439                                 return CSCF_RETURN_BREAK; //on success we break - because rest of cfg file will be executed by async process
1440                 } else {
1441                                 create_return_code(CSCF_RETURN_TRUE);
1442                                 tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
1443                                 if (saved_t_data) {
1444                                                 free_saved_transaction_global_data(saved_t_data); //no aar sent so we must free the global data
1445                                 }
1446                                 //return CSCF_RETURN_ERROR;
1447                                 return CSCF_RETURN_TRUE;
1448                 }
1449 error:
1450                 LM_ERR("Error trying to send AAR\n");
1451                 if (!aar_sent) {
1452                                 tmb.t_cancel_suspend(saved_t_data->tindex, saved_t_data->tlabel);
1453                                 if (saved_t_data) {
1454
1455                                                 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
1456                                                 //otherwise the callback will segfault
1457                                 }
1458                 }
1459                 return CSCF_RETURN_ERROR;
1460                 //return CSCF_RETURN_FALSE;
1461 }
1462
1463 static int fixup_aar_register(void** param, int param_no)
1464 {
1465                 //    udomain_t* d;
1466                 //    aar_param_t *ap;
1467                 //
1468                 //    if (param_no != 1)
1469                 //        return 0;
1470                 //    ap = (aar_param_t*) pkg_malloc(sizeof (aar_param_t));
1471                 //    if (ap == NULL) {
1472                 //        LM_ERR("no more pkg\n");
1473                 //        return -1;
1474                 //    }
1475                 //    memset(ap, 0, sizeof (aar_param_t));
1476                 //    ap->paction = get_action_from_param(param, param_no);
1477                 //
1478                 //    if (ul.register_udomain((char*) *param, &d) < 0) {
1479                 //        LM_ERR("failed to register domain\n");
1480                 //        return E_UNSPEC;
1481                 //    }
1482                 //    ap->domain = d;
1483                 //
1484                 //    *param = (void*) ap;
1485                 //    return 0;
1486                 if (strlen((char*) *param) <= 0) {
1487                                 LM_ERR("empty parameter %d not allowed\n", param_no);
1488                                 return -1;
1489                 }
1490
1491                 if (param_no == 1) { //route name - static or dynamic string (config vars)
1492                                 if (fixup_spve_null(param, param_no) < 0)
1493                                                 return -1;
1494                                 return 0;
1495                 } else if (param_no == 2) {
1496                                 udomain_t* d;
1497
1498                                 if (ul.register_udomain((char*) *param, &d) < 0) {
1499                                                 LM_ERR("Error doing fixup on assign save");
1500
1501                                                 return -1;
1502                                 }
1503                                 *param = (void*) d;
1504                 }
1505
1506                 return 0;
1507 }
1508
1509 static int fixup_aar(void** param, int param_no)
1510 {
1511                 str s;
1512                 int num;
1513
1514                 //param 3 can be empty
1515                 if (param_no != 3 && strlen((char*) *param) <= 0) {
1516                                 LM_ERR("empty parameter %d not allowed\n", param_no);
1517                                 return -1;
1518                 }
1519
1520                 if (param_no == 1) { //route name - static or dynamic string (config vars)
1521                                 if (fixup_spve_null(param, param_no) < 0)
1522                                                 return -1;
1523                                 return 0;
1524                 } else if (param_no == 3) {
1525                                 return fixup_var_str_12(param, param_no);
1526                 } else if (param_no == 4) {
1527                                 /*convert to int */
1528                                 s.s = (char*) *param;
1529                                 s.len = strlen(s.s);
1530                                 if (str2sint(&s, &num) == 0) {
1531                                                 pkg_free(*param);
1532                                                 *param = (void*) (unsigned long) num;
1533                                                 return 0;
1534                                 }
1535                                 LM_ERR("Bad subscription id: <%s>n", (char*) (*param));
1536
1537                                 return E_CFG;
1538                 }
1539
1540                 return 0;
1541 }
1542
1543 /*create a return code to be passed back into config file*/
1544 int create_return_code(int result)
1545 {
1546                 int rc;
1547                 int_str avp_val, avp_name;
1548                 avp_name.s.s = "aar_return_code";
1549                 avp_name.s.len = 15;
1550
1551                 LM_DBG("Creating return code of [%d] for aar_return_code\n", result);
1552                 //build avp spec for uaa_return_code
1553                 avp_val.n = result;
1554
1555                 rc = add_avp(AVP_NAME_STR, avp_name, avp_val);
1556
1557                 if (rc < 0)
1558                                 LM_ERR("couldn't create [aar_return_code] AVP\n");
1559                 else
1560                                 LM_DBG("created AVP successfully : [%.*s]\n", avp_name.s.len, avp_name.s.s);
1561
1562                 return rc;
1563 }