123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- /*
- * $Id$
- *
- * Copyright (C) 2012 Smile Communications, [email protected]
- * Copyright (C) 2012 Smile Communications, [email protected]
- *
- * The initial version of this code was written by Dragos Vingarzan
- * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
- * Fruanhofer Institute. It was and still is maintained in a separate
- * branch of the original SER. We are therefore migrating it to
- * Kamailio/SR and look forward to maintaining it from here on out.
- * 2011/2012 Smile Communications, Pty. Ltd.
- * ported/maintained/improved by
- * Jason Penton (jason(dot)penton(at)smilecoms.com and
- * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
- * effort to add full IMS support to Kamailio/SR using a new and
- * improved architecture
- *
- * NB: Alot of this code was originally part of OpenIMSCore,
- * FhG Fokus.
- * Copyright (C) 2004-2006 FhG Fokus
- * Thanks for great work! This is an effort to
- * break apart the various CSCF functions into logically separate
- * components. We hope this will drive wider use. We also feel
- * that in this way the architecture is more complete and thereby easier
- * to manage in the Kamailio/SR environment
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
- #include <time.h>
- #include "sem.h"
- #include "../ims_usrloc_pcscf/usrloc.h"
- #include "../dialog_ng/dlg_load.h"
- #include "../cdp/session.h"
- #include "mod.h"
- #include "cdpeventprocessor.h"
- #include "rx_str.h"
- cdp_cb_event_list_t *cdp_event_list = 0;
- extern usrloc_api_t ul;
- extern struct dlg_binds dlgb;
- extern int cdp_event_latency;
- extern int cdp_event_threshold;
- extern int cdp_event_latency_loglevel;
- int init_cdp_cb_event_list() {
- cdp_event_list = shm_malloc(sizeof (cdp_cb_event_list_t));
- if (!cdp_event_list) {
- LM_ERR("No more SHM mem\n");
- return 0;
- }
- memset(cdp_event_list, 0, sizeof (cdp_cb_event_list_t));
- cdp_event_list->lock = lock_alloc();
- if (!cdp_event_list->lock) {
- LM_ERR("failed to create cdp event list lock\n");
- return 0;
- }
- cdp_event_list->lock = lock_init(cdp_event_list->lock);
- sem_new(cdp_event_list->empty, 0); //pre-locked - as we assume list is empty at start
- return 1;
- }
- void destroy_cdp_cb_event_list() {
- cdp_cb_event_t *ev, *tmp;
- lock_get(cdp_event_list->lock);
- ev = cdp_event_list->head;
- while (ev) {
- tmp = ev->next;
- free_cdp_cb_event(ev);
- ev = tmp;
- }
- lock_destroy(cdp_event_list->lock);
- lock_dealloc(cdp_event_list->lock);
- shm_free(cdp_event_list);
- }
- cdp_cb_event_t* new_cdp_cb_event(int event, str *rx_session_id, rx_authsessiondata_t *session_data) {
- cdp_cb_event_t *new_event = shm_malloc(sizeof (cdp_cb_event_t));
- if (!new_event) {
- LM_ERR("no more shm mem\n");
- return NULL;
- }
- memset(new_event, 0, sizeof (cdp_cb_event_t));
- //we have to make a copy of the rx session id because it is not in shm mem
- if ((rx_session_id->len > 0) && rx_session_id->s) {
- LM_DBG("Creating new event for rx session [%.*s]\n", rx_session_id->len, rx_session_id->s);
- new_event->rx_session_id.s = (char*) shm_malloc(rx_session_id->len);
- if (!new_event->rx_session_id.s) {
- LM_ERR("no more shm memory\n");
- shm_free(new_event);
- return NULL;
- }
- memcpy(new_event->rx_session_id.s, rx_session_id->s, rx_session_id->len);
- new_event->rx_session_id.len = rx_session_id->len;
- }
- new_event->event = event;
- new_event->registered = time(NULL);
- new_event->session_data = session_data; //session_data is already in shm mem
- return new_event;
- }
- //add to tail
- void push_cdp_cb_event(cdp_cb_event_t* event) {
- lock_get(cdp_event_list->lock);
- if (cdp_event_list->head == 0) { //empty list
- cdp_event_list->head = cdp_event_list->tail = event;
- } else {
- cdp_event_list->tail->next = event;
- cdp_event_list->tail = event;
- }
- sem_release(cdp_event_list->empty);
- lock_release(cdp_event_list->lock);
- }
- //pop from head
- cdp_cb_event_t* pop_cdp_cb_event() {
- cdp_cb_event_t *ev;
- lock_get(cdp_event_list->lock);
- while (cdp_event_list->head == 0) {
- lock_release(cdp_event_list->lock);
- sem_get(cdp_event_list->empty);
- lock_get(cdp_event_list->lock);
- }
- ev = cdp_event_list->head;
- cdp_event_list->head = ev->next;
- if (ev == cdp_event_list->tail) { //list now empty
- cdp_event_list->tail = 0;
- }
- ev->next = 0; //make sure whoever gets this cant access our list
- lock_release(cdp_event_list->lock);
- return ev;
- }
- /*main event process function*/
- void cdp_cb_event_process() {
- cdp_cb_event_t *ev;
- udomain_t* domain;
- pcontact_t* pcontact;
- str release_reason = {"QoS released", 12}; /* TODO: This could be a module parameter */
- struct pcontact_info ci;
- memset(&ci, 0, sizeof (struct pcontact_info));
- for (;;) {
- ev = pop_cdp_cb_event();
- if (cdp_event_latency) { //track delays
- unsigned int diff = time(NULL) - ev->registered;
- if (diff > cdp_event_threshold) {
- switch (cdp_event_latency_loglevel) {
- case 0:
- LM_ERR("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
- break;
- case 1:
- LM_WARN("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
- break;
- case 2:
- LM_INFO("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
- break;
- case 3:
- LM_DBG("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
- break;
- default:
- LM_DBG("Unknown log level....printing as debug\n");
- LM_DBG("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
- break;
- }
- }
- }
- LM_DBG("processing event [%d]\n", ev->event);
- rx_authsessiondata_t *p_session_data = ev->session_data;
- str *rx_session_id = &ev->rx_session_id;
- switch (ev->event) {
- case AUTH_EV_SESSION_TIMEOUT:
- case AUTH_EV_SESSION_GRACE_TIMEOUT:
- case AUTH_EV_SESSION_LIFETIME_TIMEOUT:
- LM_DBG("Rx CDP Session: AUTH EV SESSION TIMEOUT or GRACE TIMEOUT or LIFE TIMEOUT\n");
- if (p_session_data->subscribed_to_signaling_path_status) {
- LM_DBG("Received notification of CDP timeout of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
- " and domain [%.*s]\n",
- rx_session_id->len, rx_session_id->s,
- p_session_data->registration_aor.len, p_session_data->registration_aor.s,
- p_session_data->domain.len, p_session_data->domain.s);
- LM_DBG("This is a subscription to signalling bearer session");
- } else {
- LM_DBG("Received notification of CDP timeout of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
- " and domain [%.*s]\n",
- rx_session_id->len, rx_session_id->s,
- p_session_data->registration_aor.len, p_session_data->registration_aor.s,
- p_session_data->domain.len, p_session_data->domain.s);
- LM_DBG("This is a media bearer session session");
- }
- break;
- case AUTH_EV_SERVICE_TERMINATED:
- LM_DBG("Rx CDP Session: Service terminated\n");
-
- if (p_session_data->subscribed_to_signaling_path_status) {
- LM_DBG("Received notification of CDP TERMINATE of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
- " and domain [%.*s]\n",
- rx_session_id->len, rx_session_id->s,
- p_session_data->registration_aor.len, p_session_data->registration_aor.s,
- p_session_data->domain.len, p_session_data->domain.s);
- LM_DBG("This is a subscription to signalling bearer session");
-
- //instead of removing the contact from usrloc_pcscf we just change the state of the contact to TERMINATE_PENDING_NOTIFY
- //pcscf_registrar sees this, sends a SIP PUBLISH and on SIP NOTIFY the contact is deleted
-
- if (ul.register_udomain(p_session_data->domain.s, &domain)
- < 0) {
- LM_DBG("Unable to register usrloc domain....aborting\n");
- return;
- }
- ul.lock_udomain(domain, &p_session_data->registration_aor);
- if (ul.get_pcontact(domain, &p_session_data->registration_aor,
- &pcontact) != 0) {
- LM_DBG("no contact found for terminated Rx reg session..... ignoring\n");
- } else {
- LM_DBG("Updating contact [%.*s] after Rx reg session terminated, setting state to PCONTACT_DEREG_PENDING_PUBLISH\n", pcontact->aor.len, pcontact->aor.s);
- ci.reg_state = PCONTACT_DEREG_PENDING_PUBLISH;
- ci.num_service_routes = 0;
- ul.update_pcontact(domain, &ci, pcontact);
- }
- ul.unlock_udomain(domain, &p_session_data->registration_aor);
- } else {
- LM_DBG("Received notification of CDP TERMINATE of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
- " and domain [%.*s]\n",
- rx_session_id->len, rx_session_id->s,
- p_session_data->registration_aor.len, p_session_data->registration_aor.s,
- p_session_data->domain.len, p_session_data->domain.s);
- LM_DBG("This is a media bearer session session");
- LM_DBG("Terminating dialog with callid, ftag, ttag: [%.*s], [%.*s], [%.*s]\n",
- p_session_data->callid.len, p_session_data->callid.s,
- p_session_data->ftag.len, p_session_data->ftag.s,
- p_session_data->ttag.len, p_session_data->ttag.s);
- dlgb.terminate_dlg(&p_session_data->callid,
- &p_session_data->ftag, &p_session_data->ttag, NULL,
- &release_reason);
- }
-
- //free callback data
- if (p_session_data) {
- shm_free(p_session_data);
- p_session_data = 0;
- }
- break;
- default:
- break;
- }
- free_cdp_cb_event(ev);
- }
- }
- void free_cdp_cb_event(cdp_cb_event_t *ev) {
- if (ev) {
- LM_DBG("Freeing cdpb CB event structure\n");
- if (ev->rx_session_id.len > 0 && ev->rx_session_id.s) {
- LM_DBG("about to free string from cdp CB event [%.*s]\n", ev->rx_session_id.len, ev->rx_session_id.s);
- shm_free(ev->rx_session_id.s);
- }
- shm_free(ev);
- }
- }
|