2
0

cdpeventprocessor.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2012 Smile Communications, [email protected]
  5. * Copyright (C) 2012 Smile Communications, [email protected]
  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  43. *
  44. */
  45. #include <time.h>
  46. #include "sem.h"
  47. #include "../ims_usrloc_pcscf/usrloc.h"
  48. #include "../dialog_ng/dlg_load.h"
  49. #include "../cdp/session.h"
  50. #include "mod.h"
  51. #include "cdpeventprocessor.h"
  52. #include "rx_str.h"
  53. cdp_cb_event_list_t *cdp_event_list = 0;
  54. extern usrloc_api_t ul;
  55. extern struct dlg_binds dlgb;
  56. extern int cdp_event_latency;
  57. extern int cdp_event_threshold;
  58. extern int cdp_event_latency_loglevel;
  59. int init_cdp_cb_event_list() {
  60. cdp_event_list = shm_malloc(sizeof (cdp_cb_event_list_t));
  61. if (!cdp_event_list) {
  62. LM_ERR("No more SHM mem\n");
  63. return 0;
  64. }
  65. memset(cdp_event_list, 0, sizeof (cdp_cb_event_list_t));
  66. cdp_event_list->lock = lock_alloc();
  67. if (!cdp_event_list->lock) {
  68. LM_ERR("failed to create cdp event list lock\n");
  69. return 0;
  70. }
  71. cdp_event_list->lock = lock_init(cdp_event_list->lock);
  72. sem_new(cdp_event_list->empty, 0); //pre-locked - as we assume list is empty at start
  73. return 1;
  74. }
  75. void destroy_cdp_cb_event_list() {
  76. cdp_cb_event_t *ev, *tmp;
  77. lock_get(cdp_event_list->lock);
  78. ev = cdp_event_list->head;
  79. while (ev) {
  80. tmp = ev->next;
  81. free_cdp_cb_event(ev);
  82. ev = tmp;
  83. }
  84. lock_destroy(cdp_event_list->lock);
  85. lock_dealloc(cdp_event_list->lock);
  86. shm_free(cdp_event_list);
  87. }
  88. cdp_cb_event_t* new_cdp_cb_event(int event, str *rx_session_id, rx_authsessiondata_t *session_data) {
  89. cdp_cb_event_t *new_event = shm_malloc(sizeof (cdp_cb_event_t));
  90. if (!new_event) {
  91. LM_ERR("no more shm mem\n");
  92. return NULL;
  93. }
  94. memset(new_event, 0, sizeof (cdp_cb_event_t));
  95. //we have to make a copy of the rx session id because it is not in shm mem
  96. if ((rx_session_id->len > 0) && rx_session_id->s) {
  97. LM_DBG("Creating new event for rx session [%.*s]\n", rx_session_id->len, rx_session_id->s);
  98. new_event->rx_session_id.s = (char*) shm_malloc(rx_session_id->len);
  99. if (!new_event->rx_session_id.s) {
  100. LM_ERR("no more shm memory\n");
  101. shm_free(new_event);
  102. return NULL;
  103. }
  104. memcpy(new_event->rx_session_id.s, rx_session_id->s, rx_session_id->len);
  105. new_event->rx_session_id.len = rx_session_id->len;
  106. }
  107. new_event->event = event;
  108. new_event->registered = time(NULL);
  109. new_event->session_data = session_data; //session_data is already in shm mem
  110. return new_event;
  111. }
  112. //add to tail
  113. void push_cdp_cb_event(cdp_cb_event_t* event) {
  114. lock_get(cdp_event_list->lock);
  115. if (cdp_event_list->head == 0) { //empty list
  116. cdp_event_list->head = cdp_event_list->tail = event;
  117. } else {
  118. cdp_event_list->tail->next = event;
  119. cdp_event_list->tail = event;
  120. }
  121. sem_release(cdp_event_list->empty);
  122. lock_release(cdp_event_list->lock);
  123. }
  124. //pop from head
  125. cdp_cb_event_t* pop_cdp_cb_event() {
  126. cdp_cb_event_t *ev;
  127. lock_get(cdp_event_list->lock);
  128. while (cdp_event_list->head == 0) {
  129. lock_release(cdp_event_list->lock);
  130. sem_get(cdp_event_list->empty);
  131. lock_get(cdp_event_list->lock);
  132. }
  133. ev = cdp_event_list->head;
  134. cdp_event_list->head = ev->next;
  135. if (ev == cdp_event_list->tail) { //list now empty
  136. cdp_event_list->tail = 0;
  137. }
  138. ev->next = 0; //make sure whoever gets this cant access our list
  139. lock_release(cdp_event_list->lock);
  140. return ev;
  141. }
  142. /*main event process function*/
  143. void cdp_cb_event_process() {
  144. cdp_cb_event_t *ev;
  145. udomain_t* domain;
  146. pcontact_t* pcontact;
  147. str release_reason = {"QoS released", 12}; /* TODO: This could be a module parameter */
  148. struct pcontact_info ci;
  149. memset(&ci, 0, sizeof (struct pcontact_info));
  150. for (;;) {
  151. ev = pop_cdp_cb_event();
  152. if (cdp_event_latency) { //track delays
  153. unsigned int diff = time(NULL) - ev->registered;
  154. if (diff > cdp_event_threshold) {
  155. switch (cdp_event_latency_loglevel) {
  156. case 0:
  157. LM_ERR("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
  158. break;
  159. case 1:
  160. LM_WARN("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
  161. break;
  162. case 2:
  163. LM_INFO("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
  164. break;
  165. case 3:
  166. LM_DBG("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
  167. break;
  168. default:
  169. LM_DBG("Unknown log level....printing as debug\n");
  170. LM_DBG("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
  171. break;
  172. }
  173. }
  174. }
  175. LM_DBG("processing event [%d]\n", ev->event);
  176. rx_authsessiondata_t *p_session_data = ev->session_data;
  177. str *rx_session_id = &ev->rx_session_id;
  178. switch (ev->event) {
  179. case AUTH_EV_SESSION_TIMEOUT:
  180. case AUTH_EV_SESSION_GRACE_TIMEOUT:
  181. case AUTH_EV_SESSION_LIFETIME_TIMEOUT:
  182. LM_DBG("Rx CDP Session: AUTH EV SESSION TIMEOUT or GRACE TIMEOUT or LIFE TIMEOUT\n");
  183. if (p_session_data->subscribed_to_signaling_path_status) {
  184. LM_DBG("Received notification of CDP timeout of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
  185. " and domain [%.*s]\n",
  186. rx_session_id->len, rx_session_id->s,
  187. p_session_data->registration_aor.len, p_session_data->registration_aor.s,
  188. p_session_data->domain.len, p_session_data->domain.s);
  189. LM_DBG("This is a subscription to signalling bearer session");
  190. } else {
  191. LM_DBG("Received notification of CDP timeout of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
  192. " and domain [%.*s]\n",
  193. rx_session_id->len, rx_session_id->s,
  194. p_session_data->registration_aor.len, p_session_data->registration_aor.s,
  195. p_session_data->domain.len, p_session_data->domain.s);
  196. LM_DBG("This is a media bearer session session");
  197. }
  198. break;
  199. case AUTH_EV_SERVICE_TERMINATED:
  200. LM_DBG("Rx CDP Session: Service terminated\n");
  201. if (p_session_data->subscribed_to_signaling_path_status) {
  202. LM_DBG("Received notification of CDP TERMINATE of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
  203. " and domain [%.*s]\n",
  204. rx_session_id->len, rx_session_id->s,
  205. p_session_data->registration_aor.len, p_session_data->registration_aor.s,
  206. p_session_data->domain.len, p_session_data->domain.s);
  207. LM_DBG("This is a subscription to signalling bearer session");
  208. //instead of removing the contact from usrloc_pcscf we just change the state of the contact to TERMINATE_PENDING_NOTIFY
  209. //pcscf_registrar sees this, sends a SIP PUBLISH and on SIP NOTIFY the contact is deleted
  210. if (ul.register_udomain(p_session_data->domain.s, &domain)
  211. < 0) {
  212. LM_DBG("Unable to register usrloc domain....aborting\n");
  213. return;
  214. }
  215. ul.lock_udomain(domain, &p_session_data->registration_aor);
  216. if (ul.get_pcontact(domain, &p_session_data->registration_aor,
  217. &pcontact) != 0) {
  218. LM_DBG("no contact found for terminated Rx reg session..... ignoring\n");
  219. } else {
  220. LM_DBG("Updating contact [%.*s] after Rx reg session terminated, setting state to PCONTACT_DEREG_PENDING_PUBLISH\n", pcontact->aor.len, pcontact->aor.s);
  221. ci.reg_state = PCONTACT_DEREG_PENDING_PUBLISH;
  222. ci.num_service_routes = 0;
  223. ul.update_pcontact(domain, &ci, pcontact);
  224. }
  225. ul.unlock_udomain(domain, &p_session_data->registration_aor);
  226. } else {
  227. LM_DBG("Received notification of CDP TERMINATE of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
  228. " and domain [%.*s]\n",
  229. rx_session_id->len, rx_session_id->s,
  230. p_session_data->registration_aor.len, p_session_data->registration_aor.s,
  231. p_session_data->domain.len, p_session_data->domain.s);
  232. LM_DBG("This is a media bearer session session");
  233. LM_DBG("Terminating dialog with callid, ftag, ttag: [%.*s], [%.*s], [%.*s]\n",
  234. p_session_data->callid.len, p_session_data->callid.s,
  235. p_session_data->ftag.len, p_session_data->ftag.s,
  236. p_session_data->ttag.len, p_session_data->ttag.s);
  237. dlgb.terminate_dlg(&p_session_data->callid,
  238. &p_session_data->ftag, &p_session_data->ttag, NULL,
  239. &release_reason);
  240. }
  241. //free callback data
  242. if (p_session_data) {
  243. shm_free(p_session_data);
  244. p_session_data = 0;
  245. }
  246. break;
  247. default:
  248. break;
  249. }
  250. free_cdp_cb_event(ev);
  251. }
  252. }
  253. void free_cdp_cb_event(cdp_cb_event_t *ev) {
  254. if (ev) {
  255. LM_DBG("Freeing cdpb CB event structure\n");
  256. if (ev->rx_session_id.len > 0 && ev->rx_session_id.s) {
  257. LM_DBG("about to free string from cdp CB event [%.*s]\n", ev->rx_session_id.len, ev->rx_session_id.s);
  258. shm_free(ev->rx_session_id.s);
  259. }
  260. shm_free(ev);
  261. }
  262. }