rls_mod.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. #include "rls_mod.h"
  2. #include "../../sr_module.h"
  3. #include "../../timer_ticks.h"
  4. #include "../../mem/mem.h"
  5. #include "../../mem/shm_mem.h"
  6. #include <libxml/parser.h>
  7. #include <cds/memory.h>
  8. #include <cds/ptr_vector.h>
  9. #include <cds/logger.h>
  10. #include <cds/cds.h>
  11. #include <presence/qsa.h>
  12. #include "rl_subscription.h"
  13. #include "rls_handler.h"
  14. #include "rpc.h"
  15. #include "uri_ops.h"
  16. #include "time_event_manager.h"
  17. #include <time.h>
  18. MODULE_VERSION
  19. int rls_mod_init(void);
  20. void rls_mod_destroy(void);
  21. int rls_child_init(int _rank);
  22. static int rls_subscribe_fixup(void** param, int param_no);
  23. /* authorization parameters */
  24. char *auth_type_str = NULL; /* type of authorization: none,implicit,xcap */
  25. int db_mode = 0; /* 0 -> no DB, 1 -> write through */
  26. char *db_url = NULL;
  27. int reduce_xcap_needs = 0;
  28. /* internal data members */
  29. /* static ptr_vector_t *xcap_servers = NULL; */
  30. db_con_t* rls_db = NULL; /* database connection handle */
  31. db_func_t rls_dbf; /* database functions */
  32. /* one shot timer for reloading data from DB -
  33. they can not be reloaded in init or
  34. child_init due to internal subscriptions
  35. to other modules (may be not itialised
  36. yet) */
  37. static int init_timer_delay = 3;
  38. /* parameters for optimizations */
  39. int max_notifications_at_once = 1000000;
  40. /* timer for processing notifications from QSA */
  41. int rls_timer_interval = 10;
  42. /* ignore if NOTIFY times out (don't destroy subscription */
  43. int rls_ignore_408_on_notify = 0;
  44. /* maximum nested list level (if 0, no nested lists are possible,
  45. * if 1 only one nested list level is possible, if 2 it is possible to
  46. * have lists in lists, ..., unlimited if -1) */
  47. int max_list_nesting_level = -1;
  48. /** Exported functions */
  49. static cmd_export_t cmds[]={
  50. /* {"handle_r_subscription", handle_r_subscription, 0, subscribe_fixup, REQUEST_ROUTE | FAILURE_ROUTE}, */
  51. {"handle_rls_subscription", (cmd_function)handle_rls_subscription, 1,
  52. rls_subscribe_fixup, REQUEST_ROUTE | FAILURE_ROUTE},
  53. {"is_simple_rls_target", is_simple_rls_target, 1, NULL, REQUEST_ROUTE | FAILURE_ROUTE},
  54. {"query_rls_services", query_rls_services, 0, NULL, REQUEST_ROUTE | FAILURE_ROUTE},
  55. {"query_resource_list", query_resource_list, 1, NULL, REQUEST_ROUTE | FAILURE_ROUTE},
  56. {"have_flat_list", have_flat_list, 0, NULL, REQUEST_ROUTE | FAILURE_ROUTE},
  57. {0, 0, 0, 0, 0}
  58. };
  59. /** Exported parameters */
  60. static param_export_t params[]={
  61. {"min_expiration", PARAM_INT, &rls_min_expiration },
  62. {"max_expiration", PARAM_INT, &rls_max_expiration },
  63. {"default_expiration", PARAM_INT, &rls_default_expiration },
  64. {"auth", PARAM_STRING, &auth_type_str }, /* type of authorization: none, implicit, xcap, ... */
  65. {"db_mode", PARAM_INT, &db_mode },
  66. {"db_url", PARAM_STRING, &db_url },
  67. {"reduce_xcap_needs", PARAM_INT, &reduce_xcap_needs },
  68. {"max_notifications_at_once", PARAM_INT, &max_notifications_at_once },
  69. {"timer_interval", PARAM_INT, &rls_timer_interval },
  70. {"max_list_nesting_level", PARAM_INT, &max_list_nesting_level },
  71. {"expiration_timer_period", PARAM_INT, &rls_expiration_timer_period },
  72. {"ignore_408_on_notify", PARAM_INT, &rls_ignore_408_on_notify },
  73. {"init_timer_delay", PARAM_INT, &init_timer_delay }, /* timer for delayed DB reload (due to internal subscriptions can't be reloaded from init or child init) */
  74. {0, 0, 0}
  75. };
  76. struct module_exports exports = {
  77. "rls",
  78. cmds, /* Exported functions */
  79. rls_rpc_methods, /* RPC methods */
  80. params, /* Exported parameters */
  81. rls_mod_init, /* module initialization function */
  82. 0, /* response function*/
  83. rls_mod_destroy, /* pa_destroy, / * destroy function */
  84. 0, /* oncancel function */
  85. rls_child_init /* per-child init function */
  86. };
  87. struct tm_binds tmb;
  88. dlg_func_t dlg_func;
  89. fill_xcap_params_func fill_xcap_params = NULL;
  90. int use_db = 0;
  91. int rls_min_expiration = 60;
  92. int rls_max_expiration = 7200;
  93. int rls_default_expiration = 3761;
  94. int rls_expiration_timer_period = 10;
  95. rls_auth_params_t rls_auth_params; /* structure filled according to parameters (common for all XCAP servers now) */
  96. char *xcap_server = NULL; /* XCAP server URI */
  97. /* TODO: settings of other xcap parameters (auth, ssl, ...) */
  98. static int set_auth_params(rls_auth_params_t *dst, const char *auth_type_str)
  99. {
  100. if (!auth_type_str) {
  101. LOG(L_ERR, "no subscription authorization type given, using \'implicit\'!\n");
  102. dst->type = rls_auth_none;
  103. return 0;
  104. }
  105. if (strcmp(auth_type_str, "xcap") == 0) {
  106. dst->type = rls_auth_xcap;
  107. return 0;
  108. }
  109. if (strcmp(auth_type_str, "none") == 0) {
  110. dst->type = rls_auth_none;
  111. LOG(L_WARN, "using \'none\' rls-subscription authorization!\n");
  112. return 0;
  113. }
  114. if (strcmp(auth_type_str, "implicit") == 0) {
  115. dst->type = rls_auth_implicit;
  116. return 0;
  117. }
  118. LOG(L_ERR, "Can't resolve subscription authorization type: \'%s\'."
  119. " Use one of: none, implicit, xcap.\n", auth_type_str);
  120. return -1;
  121. }
  122. static ticks_t init_timer_cb(ticks_t ticks, struct timer_ln* tl, void* data)
  123. {
  124. /* initialization (like read data from database) which can trigger
  125. * database operations in other modules/... */
  126. if (use_db && (rls_db)) {
  127. INFO("reading RLS data from database\n");
  128. rls_lock();
  129. db_load_rls();
  130. rls_unlock();
  131. }
  132. if (data) {
  133. mem_free(data);
  134. /* ERR("freeing myself!\n"); */
  135. }
  136. return 0; /* one shot timer */
  137. }
  138. int rls_mod_init(void)
  139. {
  140. load_tm_f load_tm;
  141. bind_dlg_mod_f bind_dlg;
  142. struct timer_ln *i_timer = NULL;
  143. DEBUG_LOG("RLS module initialization\n");
  144. /* ??? if other module uses this libraries it might be a problem ??? */
  145. xmlInitParser();
  146. DEBUG_LOG(" ... common libraries\n");
  147. qsa_initialize();
  148. if (time_event_management_init() != 0) {
  149. LOG(L_ERR, "rls_mod_init(): Can't initialize time event management!\n");
  150. return -1;
  151. }
  152. if (subscription_management_init() != 0) {
  153. LOG(L_ERR, "rls_mod_init(): Can't initialize time event management!\n");
  154. return -1;
  155. }
  156. /* import the TM auto-loading function */
  157. if ( !(load_tm=(load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
  158. LOG(L_ERR, "rls_mod_init(): Can't import tm!\n");
  159. return -1;
  160. }
  161. /* let the auto-loading function load all TM stuff */
  162. if (load_tm(&tmb)==-1) {
  163. LOG(L_ERR, "rls_mod_init(): load_tm() failed\n");
  164. return -1;
  165. }
  166. bind_dlg = (bind_dlg_mod_f)find_export("bind_dlg_mod", -1, 0);
  167. if (!bind_dlg) {
  168. LOG(L_ERR, "Can't import dlg\n");
  169. return -1;
  170. }
  171. if (bind_dlg(&dlg_func) != 0) {
  172. return -1;
  173. }
  174. if (rls_init() != 0) {
  175. return -1;
  176. }
  177. if (vs_init() != 0) {
  178. return -1;
  179. }
  180. /* xcap_servers = (ptr_vector_t*)mem_alloc(sizeof(ptr_vector_t));
  181. if (!xcap_servers) {
  182. LOG(L_ERR, "rls_mod_init(): can't allocate memory for XCAP servers vector\n");
  183. return -1;
  184. }
  185. ptr_vector_init(xcap_servers, 8); */
  186. /* set authorization type according to requested "auth type name"
  187. * and other (type specific) parameters */
  188. if (set_auth_params(&rls_auth_params, auth_type_str) != 0) return -1;
  189. use_db = 0;
  190. if (db_mode > 0) {
  191. int db_url_len = db_url ? strlen(db_url) : 0;
  192. if (!db_url_len) {
  193. LOG(L_ERR, "rls_mod_init(): no db_url specified but db_mode > 0\n");
  194. db_mode = 0;
  195. }
  196. }
  197. if (db_mode > 0) {
  198. if (bind_dbmod(db_url, &rls_dbf) < 0) {
  199. LOG(L_ERR, "rls_mod_init(): Can't bind database module via url %s\n", db_url);
  200. return -1;
  201. }
  202. if (!DB_CAPABILITY(rls_dbf, DB_CAP_ALL)) { /* ? */
  203. LOG(L_ERR, "rls_mod_init(): Database module does not implement all functions needed by the module\n");
  204. return -1;
  205. }
  206. use_db = 1;
  207. }
  208. /* once-shot timer for reloading data from DB -
  209. * needed because it can trigger database operations
  210. * in other modules and they mostly intialize their
  211. * database connection in child_init functions */
  212. i_timer = timer_alloc();
  213. if (!i_timer) {
  214. ERR("can't allocate memory for DB init timer\n");
  215. return -1;
  216. }
  217. else {
  218. timer_init(i_timer, init_timer_cb, i_timer, 0);
  219. timer_add(i_timer, S_TO_TICKS(init_timer_delay));
  220. }
  221. fill_xcap_params = (fill_xcap_params_func)find_export("fill_xcap_params", 0, -1);
  222. return 0;
  223. }
  224. int rls_child_init(int _rank)
  225. {
  226. rls_db = NULL;
  227. if (use_db) {
  228. if (_rank==PROC_INIT || _rank==PROC_MAIN || _rank==PROC_TCP_MAIN)
  229. return 0; /* do nothing for the main or tcp_main processes */
  230. if (rls_dbf.init) rls_db = rls_dbf.init(db_url);
  231. if (!rls_db) {
  232. LOG(L_ERR, "ERROR: rls_child_init(%d): "
  233. "Error while connecting database\n", _rank);
  234. return -1;
  235. }
  236. /* if (_rank == 0) {
  237. rls_lock();
  238. db_load_rls();
  239. rls_unlock();
  240. } */
  241. }
  242. return 0;
  243. }
  244. void rls_mod_destroy(void)
  245. {
  246. /*int i, cnt;
  247. char *s;*/
  248. DEBUG_LOG("RLS module cleanup\n");
  249. /* destroy used XCAP servers */
  250. /* DEBUG_LOG(" ... xcap servers\n");
  251. if (xcap_servers) {
  252. cnt = ptr_vector_size(xcap_servers);
  253. DEBUG_LOG(" count = %d\n", cnt);
  254. for (i = 0; i < cnt; i++) {
  255. s = ptr_vector_get(xcap_servers, i);
  256. if (s) {
  257. DEBUG_LOG(" ... freeing %s (%p)\n", s, s);
  258. cds_free(s);
  259. }
  260. }
  261. ptr_vector_destroy(xcap_servers);
  262. mem_free(xcap_servers);
  263. xcap_servers = NULL;
  264. } */
  265. DEBUG_LOG(" ... rls\n");
  266. rls_destroy();
  267. DEBUG_LOG(" ... vs\n");
  268. vs_destroy();
  269. DEBUG_LOG(" ... time event management\n");
  270. time_event_management_destroy();
  271. DEBUG_LOG(" %s: ... db\n", __func__);
  272. if (use_db) {
  273. if (rls_db && rls_dbf.close) rls_dbf.close(rls_db);
  274. rls_db = NULL;
  275. }
  276. DEBUG_LOG(" ... common libs\n");
  277. qsa_cleanup();
  278. /* ??? if other module uses this libraries it might be a problem ??? */
  279. /* xmlCleanupParser(); */
  280. DEBUG_LOG("RLS module cleanup finished\n");
  281. }
  282. static int rls_subscribe_fixup(void** param, int param_no)
  283. {
  284. /* char *xcap_server = NULL; */
  285. long send_errors = 0;
  286. /* if (param_no == 1) {
  287. if (!param) {
  288. LOG(L_ERR, "rls_subscribe_fixup(): XCAP server address not set!\n");
  289. return E_UNSPEC;
  290. }
  291. xcap_server = zt_strdup((char *)*param);
  292. if (!xcap_server) {
  293. LOG(L_ERR, "rls_subscribe_fixup(): Can't set XCAP server address!\n");
  294. return E_UNSPEC;
  295. }
  296. / * store not only the root string? (create a structure rather?) * /
  297. ptr_vector_add(xcap_servers, xcap_server);
  298. DEBUG_LOG("rls_subscribe_fixup(): XCAP server is %s (%p)\n", xcap_server, xcap_server);
  299. *param = (void*)xcap_server;
  300. } */
  301. if (param_no == 1) {
  302. if (param) {
  303. if (*param) send_errors = atoi(*param);
  304. }
  305. DEBUG_LOG("rls_subscribe_fixup(): send errors: %ld\n", send_errors);
  306. *param = (void*)send_errors;
  307. }
  308. return 0;
  309. }