dlg_cb.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright (C) 2006 Voice Sistem SRL
  3. *
  4. * This file is part of Kamailio, a free SIP server.
  5. *
  6. * Kamailio is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * Kamailio is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. */
  21. /*!
  22. * \file
  23. * \brief Callbacks
  24. * \ingroup dialog
  25. * Module: \ref dialog
  26. */
  27. #include "../../mem/shm_mem.h"
  28. #include "../../dprint.h"
  29. #include "dlg_hash.h"
  30. #include "dlg_cb.h"
  31. static struct dlg_head_cbl* create_cbs = 0;
  32. static struct dlg_head_cbl* load_cbs = 0;
  33. static struct dlg_cb_params params = {NULL, NULL, DLG_DIR_NONE, NULL, NULL};
  34. #define POINTER_CLOSED_MARKER ((void *)(-1))
  35. static void run_load_callback(struct dlg_callback *cb);
  36. static struct dlg_head_cbl* init_dlg_callback(void)
  37. {
  38. struct dlg_head_cbl *new_cbs;
  39. new_cbs = (struct dlg_head_cbl*)shm_malloc(sizeof(struct dlg_head_cbl));
  40. if (new_cbs==0) {
  41. LM_ERR("no more shm mem\n");
  42. return 0;
  43. }
  44. new_cbs->first = 0;
  45. new_cbs->types = 0;
  46. return new_cbs;
  47. }
  48. void destroy_dlg_callbacks_list(struct dlg_callback *cb)
  49. {
  50. struct dlg_callback *cb_t;
  51. while(cb) {
  52. cb_t = cb;
  53. cb = cb->next;
  54. if (cb_t->callback_param_free && cb_t->param) {
  55. cb_t->callback_param_free(cb_t->param);
  56. cb_t->param = NULL;
  57. }
  58. shm_free(cb_t);
  59. }
  60. }
  61. void destroy_dlg_callbacks(unsigned int types)
  62. {
  63. if (types&DLGCB_CREATED) {
  64. if (create_cbs && create_cbs!=POINTER_CLOSED_MARKER) {
  65. destroy_dlg_callbacks_list(create_cbs->first);
  66. shm_free(create_cbs);
  67. create_cbs = POINTER_CLOSED_MARKER;
  68. }
  69. }
  70. if (types&DLGCB_LOADED) {
  71. if (load_cbs && load_cbs!=POINTER_CLOSED_MARKER) {
  72. destroy_dlg_callbacks_list(load_cbs->first);
  73. shm_free(load_cbs);
  74. load_cbs = POINTER_CLOSED_MARKER;
  75. }
  76. }
  77. }
  78. int register_dlgcb(struct dlg_cell *dlg, int types, dialog_cb f,
  79. void *param, param_free_cb ff )
  80. {
  81. struct dlg_callback *cb;
  82. if ( types&DLGCB_LOADED ) {
  83. if (types!=DLGCB_LOADED) {
  84. LM_CRIT("DLGCB_LOADED type must be register alone!\n");
  85. return -1;
  86. }
  87. } else if ( types&DLGCB_CREATED ) {
  88. if (types!=DLGCB_CREATED) {
  89. LM_CRIT("DLGCB_CREATED type must be register alone!\n");
  90. return -1;
  91. }
  92. } else {
  93. if (dlg==0) {
  94. LM_CRIT("non-DLGCB_CREATED type "
  95. "must be register to a dialog (dlg missing)!\n");
  96. return -1;
  97. }
  98. }
  99. cb = (struct dlg_callback*)shm_malloc(sizeof(struct dlg_callback));
  100. if (cb==0) {
  101. LM_ERR("no more shm mem\n");
  102. return -1;
  103. }
  104. cb->types = types;
  105. cb->callback = f;
  106. cb->param = param;
  107. cb->callback_param_free = ff;
  108. if ( types==DLGCB_CREATED ) {
  109. if (load_cbs==POINTER_CLOSED_MARKER) {
  110. LM_CRIT("DLGCB_CREATED type registered after shutdown!?!\n");
  111. goto error;
  112. }
  113. if (create_cbs==0) {
  114. /* not initialized yet */
  115. if ( (create_cbs=init_dlg_callback())==NULL ) {
  116. LM_ERR("no more shm mem\n");
  117. goto error;
  118. }
  119. }
  120. cb->next = create_cbs->first;
  121. create_cbs->first = cb;
  122. create_cbs->types |= types;
  123. } else if (types==DLGCB_LOADED) {
  124. if (load_cbs==POINTER_CLOSED_MARKER) {
  125. /* run the callback on the spot */
  126. run_load_callback(cb);
  127. destroy_dlg_callbacks_list(cb);
  128. return 0;
  129. }
  130. if (load_cbs==0) {
  131. /* not initialized yet */
  132. if ( (load_cbs=init_dlg_callback())==NULL ) {
  133. LM_ERR("no more shm mem\n");
  134. goto error;
  135. }
  136. }
  137. cb->next = load_cbs->first;
  138. load_cbs->first = cb;
  139. load_cbs->types |= types;
  140. } else {
  141. cb->next = dlg->cbs.first;
  142. dlg->cbs.first = cb;
  143. dlg->cbs.types |= types;
  144. }
  145. return 0;
  146. error:
  147. shm_free(cb);
  148. return -1;
  149. }
  150. static void run_load_callback(struct dlg_callback *cb)
  151. {
  152. struct dlg_cell *dlg;
  153. unsigned int i;
  154. params.req = NULL;
  155. params.rpl = NULL;
  156. params.direction = DLG_DIR_NONE;
  157. params.param = &cb->param;
  158. for( i=0 ; i<d_table->size ; i++ ) {
  159. for( dlg=d_table->entries[i].first ; dlg ; dlg=dlg->next )
  160. cb->callback( dlg, DLGCB_LOADED, &params );
  161. }
  162. return;
  163. }
  164. void run_load_callbacks( void )
  165. {
  166. struct dlg_callback *cb;
  167. if (load_cbs && load_cbs!=POINTER_CLOSED_MARKER) {
  168. for ( cb=load_cbs->first; cb; cb=cb->next )
  169. run_load_callback( cb );
  170. }
  171. return;
  172. }
  173. void run_create_callbacks(struct dlg_cell *dlg, struct sip_msg *msg)
  174. {
  175. struct dlg_callback *cb;
  176. if (create_cbs==NULL || create_cbs->first==NULL)
  177. return;
  178. params.req = msg;
  179. params.rpl = NULL;
  180. /* initial request goes DOWNSTREAM all the time */
  181. params.direction = DLG_DIR_DOWNSTREAM;
  182. /* avoid garbage due static structure */
  183. params.param = NULL;
  184. params.dlg_data = NULL;
  185. for ( cb=create_cbs->first; cb; cb=cb->next) {
  186. LM_DBG("dialog=%p\n",dlg);
  187. params.param = &cb->param;
  188. cb->callback( dlg, DLGCB_CREATED, &params );
  189. }
  190. return;
  191. }
  192. void run_dlg_callbacks( int type ,
  193. struct dlg_cell *dlg,
  194. struct sip_msg *req,
  195. struct sip_msg *rpl,
  196. unsigned int dir, void *dlg_data)
  197. {
  198. struct dlg_callback *cb;
  199. params.req = req;
  200. params.rpl = rpl;
  201. params.direction = dir;
  202. params.dlg_data = dlg_data;
  203. if (dlg->cbs.first==0 || ((dlg->cbs.types)&type)==0 )
  204. return;
  205. for ( cb=dlg->cbs.first; cb; cb=cb->next) {
  206. if ( (cb->types)&type ) {
  207. LM_DBG("dialog=%p, type=%d\n", dlg, type);
  208. params.param = &cb->param;
  209. cb->callback( dlg, type, &params );
  210. }
  211. }
  212. return;
  213. }