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