rl_subscription.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. #include "rl_subscription.h"
  2. #include "rls_mod.h"
  3. #include <cds/dstring.h>
  4. #include <cds/list.h>
  5. #include <cds/logger.h>
  6. #include "result_codes.h"
  7. #include "rlmi_doc.h"
  8. #include <xcap/resource_list.h>
  9. #include <presence/pres_doc.h>
  10. #include "../../str.h"
  11. #include "../../id.h"
  12. #include "../../dprint.h"
  13. #include "../../mem/mem.h"
  14. #include "../../mem/shm_mem.h"
  15. #include "../../lock_alloc.h"
  16. #include "../../ut.h"
  17. #include "../../parser/hf.h"
  18. #include "../../parser/parse_from.h"
  19. #include "../../data_lump_rpl.h"
  20. typedef struct {
  21. dlg_id_t id;
  22. char buf[1];
  23. } rls_notify_cb_param_t;
  24. subscription_manager_t *rls_manager = NULL;
  25. #define METHOD_NOTIFY "NOTIFY"
  26. /************* Helper functions for TM callback ************/
  27. static rls_notify_cb_param_t *create_notify_cb_param(rl_subscription_t *s)
  28. {
  29. rls_notify_cb_param_t *cbd;
  30. int size;
  31. dlg_t *dlg;
  32. if (!s) return NULL;
  33. if (s->type != rls_external_subscription) return NULL;
  34. dlg = s->u.external.dialog;
  35. if (!dlg) return NULL;
  36. size = sizeof(*cbd) +
  37. dlg->id.call_id.len +
  38. dlg->id.rem_tag.len +
  39. dlg->id.loc_tag.len;
  40. cbd = (rls_notify_cb_param_t*)mem_alloc(size);
  41. if (!cbd) {
  42. ERR("can't allocate memory (%d bytes)\n", size);
  43. return NULL;
  44. }
  45. cbd->id.call_id.s = cbd->buf;
  46. cbd->id.call_id.len = dlg->id.call_id.len;
  47. cbd->id.rem_tag.s = cbd->id.call_id.s + cbd->id.call_id.len;
  48. cbd->id.rem_tag.len = dlg->id.rem_tag.len;
  49. cbd->id.loc_tag.s = cbd->id.rem_tag.s + cbd->id.rem_tag.len;
  50. cbd->id.loc_tag.len = dlg->id.loc_tag.len;
  51. /* copy data */
  52. if (dlg->id.call_id.s) memcpy(cbd->id.call_id.s,
  53. dlg->id.call_id.s, dlg->id.call_id.len);
  54. if (dlg->id.rem_tag.s) memcpy(cbd->id.rem_tag.s,
  55. dlg->id.rem_tag.s, dlg->id.rem_tag.len);
  56. if (dlg->id.loc_tag.s) memcpy(cbd->id.loc_tag.s,
  57. dlg->id.loc_tag.s, dlg->id.loc_tag.len);
  58. return cbd;
  59. }
  60. static void destroy_subscription(rls_notify_cb_param_t *cbd)
  61. {
  62. int res;
  63. rl_subscription_t *s = NULL;
  64. rls_lock();
  65. res = rls_find_subscription(&cbd->id.rem_tag, &cbd->id.loc_tag,
  66. &cbd->id.call_id, &s);
  67. if ((res != RES_OK) || (!s)) {
  68. /* subscription NOT found */
  69. rls_unlock();
  70. return;
  71. }
  72. rls_remove(s);
  73. rls_unlock();
  74. }
  75. /************* Helper functions for RL subscription manipulation ************/
  76. str_t * rls_get_uri(rl_subscription_t *s)
  77. {
  78. if (!s) return NULL;
  79. if (s->type == rls_external_subscription) {
  80. return &((s)->u.external.record_id);
  81. }
  82. else {
  83. return s->u.internal.record_id;
  84. }
  85. return NULL;
  86. }
  87. str_t * rls_get_package(rl_subscription_t *s)
  88. {
  89. static str presence = STR_STATIC_INIT("presence");
  90. str_t *package = NULL;
  91. if (!s) return NULL;
  92. if (s->type == rls_external_subscription)
  93. package = &((s)->u.external.package);
  94. else package = s->u.internal.package;
  95. if (!package) package = &presence;
  96. return package;
  97. }
  98. str_t * rls_get_subscriber(rl_subscription_t *subscription)
  99. {
  100. if (!subscription) return NULL;
  101. switch (subscription->type) {
  102. case rls_external_subscription:
  103. return &subscription->u.external.subscriber;
  104. case rls_internal_subscription:
  105. return subscription->u.internal.subscriber_id;
  106. }
  107. return NULL;
  108. }
  109. int add_virtual_subscriptions(rl_subscription_t *ss,
  110. flat_list_t *flat,
  111. int nesting_level)
  112. {
  113. flat_list_t *e;
  114. /* xcap_query_t xcap; */
  115. virtual_subscription_t *vs;
  116. int res = 0;
  117. str s;
  118. /* TODO: create virtual subscriptions using Accept headers
  119. * ... (for remote subscriptions) */
  120. /* go through flat list and find/create virtual subscriptions */
  121. e = flat;
  122. while (e) {
  123. s.s = e->uri;
  124. if (s.s) s.len = strlen(s.s);
  125. else s.len = 0;
  126. res = vs_create(&s, &vs, e->names, ss, nesting_level);
  127. if (res != RES_OK) {
  128. /* FIXME: remove already added members? */
  129. return res;
  130. }
  131. ptr_vector_add(&ss->vs, vs);
  132. e = e->next;
  133. }
  134. return RES_OK;
  135. }
  136. int create_virtual_subscriptions(rl_subscription_t *ss, int nesting_level)
  137. {
  138. flat_list_t *flat = NULL;
  139. int res = 0;
  140. str_t *ss_uri = NULL;
  141. str_t *ss_package = NULL;
  142. ss_uri = rls_get_uri(ss);
  143. ss_package = rls_get_package(ss);
  144. res = xcap_query_rls_services(&ss->xcap_params,
  145. ss_uri, ss_package, &flat);
  146. if (res != RES_OK) return res;
  147. /* go through flat list and find/create virtual subscriptions */
  148. res = add_virtual_subscriptions(ss, flat, nesting_level);
  149. DEBUG_LOG("rli_create_content(): freeing flat list\n");
  150. free_flat_list(flat);
  151. return RES_OK;
  152. }
  153. static void clear_change_flags(rl_subscription_t *s)
  154. {
  155. int i, cnt;
  156. virtual_subscription_t *vs;
  157. cnt = ptr_vector_size(&s->vs);
  158. for (i = 0; i < cnt; i++) {
  159. vs = ptr_vector_get(&s->vs, i);
  160. if (!vs) continue;
  161. vs->changed = 0;
  162. }
  163. s->changed = 0;
  164. }
  165. /************* RL subscription manipulation function ************/
  166. rl_subscription_t *rls_alloc_subscription(rls_subscription_type_t type)
  167. {
  168. rl_subscription_t *s;
  169. s = (rl_subscription_t*)mem_alloc(sizeof(rl_subscription_t));
  170. if (!s) {
  171. LOG(L_ERR, "rls_alloc_subscription(): can't allocate memory\n");
  172. return NULL;
  173. }
  174. memset(s, 0, sizeof(*s));
  175. s->u.external.status = subscription_uninitialized;
  176. s->u.external.usr_data = s;
  177. s->doc_version = 0;
  178. s->changed = 0;
  179. s->type = type;
  180. s->dbid[0] = 0;
  181. /* s->first_vs = NULL;
  182. s->last_vs = NULL; */
  183. str_clear(&s->from_uid);
  184. ptr_vector_init(&s->vs, 4);
  185. return s;
  186. }
  187. int rls_create_subscription(struct sip_msg *m,
  188. rl_subscription_t **dst,
  189. flat_list_t *flat,
  190. xcap_query_params_t *params)
  191. {
  192. rl_subscription_t *s;
  193. str from_uid = STR_NULL;
  194. int res;
  195. if (!dst) return RES_INTERNAL_ERR;
  196. *dst = NULL;
  197. s = rls_alloc_subscription(rls_external_subscription);
  198. if (!s) {
  199. LOG(L_ERR, "rls_create_new(): can't allocate memory\n");
  200. return RES_MEMORY_ERR;
  201. }
  202. generate_db_id(&s->dbid, s);
  203. res = sm_init_subscription_nolock(rls_manager, &s->u.external, m);
  204. if (res != RES_OK) {
  205. rls_free(s);
  206. return res;
  207. }
  208. if (params) {
  209. if (dup_xcap_params(&s->xcap_params, params) < 0) {
  210. ERR("can't duplicate xcap_params\n");
  211. rls_free(s);
  212. return -1;
  213. }
  214. }
  215. /* store pointer to this RL subscription as user data
  216. * of (low level) subscription */
  217. s->u.external.usr_data = s;
  218. if (get_from_uid(&from_uid, m) < 0) str_clear(&s->from_uid);
  219. else str_dup(&s->from_uid, &from_uid);
  220. /* res = set_rls_info(m, s, xcap_root);
  221. if (res != 0) {
  222. rls_free(s);
  223. return res;
  224. }*/
  225. res = add_virtual_subscriptions(s, flat, max_list_nesting_level);
  226. if (res != 0) {
  227. rls_free(s);
  228. return res;
  229. }
  230. if (use_db) {
  231. if (rls_db_add(s) != 0) {
  232. rls_free(s);
  233. return RES_INTERNAL_ERR; /* FIXME RES_DB_ERR */
  234. }
  235. }
  236. *dst = s;
  237. return RES_OK;
  238. }
  239. int rls_find_subscription(str *from_tag, str *to_tag, str *call_id, rl_subscription_t **dst)
  240. {
  241. subscription_data_t *s;
  242. int res;
  243. *dst = NULL;
  244. res = sm_find_subscription(rls_manager, from_tag, to_tag, call_id, &s);
  245. if ((res == RES_OK) && (s)) {
  246. if (!s->usr_data) {
  247. LOG(L_ERR, "found subscription without filled usr_data\n");
  248. return RES_INTERNAL_ERR;
  249. }
  250. else {
  251. *dst = (rl_subscription_t*)s->usr_data;
  252. return RES_OK;
  253. }
  254. }
  255. return RES_NOT_FOUND;
  256. }
  257. int rls_refresh_subscription(struct sip_msg *m, rl_subscription_t *s)
  258. {
  259. int res;
  260. if (!s) return RES_INTERNAL_ERR;
  261. if (s->type != rls_external_subscription) return RES_INTERNAL_ERR;
  262. res = sm_refresh_subscription_nolock(rls_manager, &s->u.external, m);
  263. if (use_db) rls_db_update(s);
  264. return res;
  265. }
  266. void rls_remove(rl_subscription_t *s)
  267. {
  268. if (!s) return;
  269. if (use_db) rls_db_remove(s);
  270. rls_free(s);
  271. }
  272. void rls_free(rl_subscription_t *s)
  273. {
  274. int i, cnt;
  275. virtual_subscription_t *vs;
  276. if (!s) return;
  277. if (use_db) rls_db_remove(s);
  278. cnt = ptr_vector_size(&s->vs);
  279. for (i = 0; i < cnt; i++) {
  280. vs = ptr_vector_get(&s->vs, i);
  281. if (!vs) continue;
  282. vs_free(vs);
  283. }
  284. if (s->type == rls_external_subscription) {
  285. sm_release_subscription_nolock(rls_manager, &s->u.external);
  286. /* free ONLY for external subscriptions */
  287. free_xcap_params_content(&s->xcap_params);
  288. }
  289. else {
  290. /* release_internal_subscription(s); */
  291. /* don't free xcap_params */
  292. }
  293. ptr_vector_destroy(&s->vs);
  294. str_free_content(&s->from_uid);
  295. mem_free(s);
  296. }
  297. /* void rls_notify_cb(struct cell* t, struct sip_msg* msg, int code, void *param) */
  298. static void rls_notify_cb(struct cell* t, int type, struct tmcb_params* params)
  299. {
  300. rls_notify_cb_param_t *cbd = NULL;
  301. if (!params) return;
  302. if (params->param) cbd = (rls_notify_cb_param_t *)*(params->param);
  303. if (!cbd) {
  304. ERR("BUG empty cbd parameter given to callback function\n");
  305. return;
  306. }
  307. if (params->code >= 300) { /* what else can we do with 3xx ? */
  308. int ignore = 0;
  309. switch (params->code) {
  310. case 408:
  311. if (rls_ignore_408_on_notify) ignore = 1;
  312. /* due to eyeBeam's problems with processing more NOTIFY
  313. * requests sent consequently without big delay */
  314. break;
  315. }
  316. if (!ignore) {
  317. WARN("destroying subscription from callback due to %d response on NOTIFY\n", params->code);
  318. destroy_subscription(cbd);
  319. TRACE("subscription destroyed!!!\n");
  320. }
  321. }
  322. mem_free(cbd);
  323. }
  324. static int rls_generate_notify_ext(rl_subscription_t *s, int full_info)
  325. {
  326. /* !!! the main mutex must be locked here !!! */
  327. int res;
  328. str doc;
  329. dstring_t dstr;
  330. str headers, content_type;
  331. static str method = STR_STATIC_INIT(METHOD_NOTIFY);
  332. dlg_t *dlg;
  333. int exp_time = 0;
  334. char expiration[32];
  335. str body = STR_STATIC_INIT("");
  336. int removed = 0;
  337. dlg = s->u.external.dialog;
  338. if (!dlg) return -1;
  339. DEBUG("generating external notify\n");
  340. str_clear(&doc);
  341. str_clear(&content_type);
  342. if (sm_subscription_pending(&s->u.external) != 0) {
  343. /* create the document only for non-pending subscriptions */
  344. if (create_rlmi_document(&doc, &content_type, s, full_info) != 0) {
  345. return -1;
  346. }
  347. }
  348. exp_time = sm_subscription_expires_in(rls_manager, &s->u.external);
  349. sprintf(expiration, ";expires=%d\r\n", exp_time);
  350. dstr_init(&dstr, 256);
  351. dstr_append_zt(&dstr, "Subscription-State: ");
  352. switch (s->u.external.status) {
  353. case subscription_active:
  354. dstr_append_zt(&dstr, "active");
  355. dstr_append_zt(&dstr, expiration);
  356. break;
  357. case subscription_pending:
  358. dstr_append_zt(&dstr, "pending");
  359. dstr_append_zt(&dstr, expiration);
  360. break;
  361. case subscription_terminated_pending:
  362. case subscription_terminated:
  363. dstr_append_zt(&dstr, "terminated\r\n");
  364. break;
  365. case subscription_terminated_pending_to:
  366. case subscription_terminated_to:
  367. dstr_append_zt(&dstr,
  368. "terminated;reason=timeout\r\n");
  369. break;
  370. case subscription_uninitialized:
  371. dstr_append_zt(&dstr, "pending\r\n");
  372. /* this is an error ! */
  373. LOG(L_ERR, "sending NOTIFY for an unitialized subscription!\n");
  374. break;
  375. }
  376. dstr_append_str(&dstr, &s->u.external.contact);
  377. /* required by RFC 3261 */
  378. dstr_append_zt(&dstr, "Max-Forwards: 70\r\n");
  379. dstr_append_zt(&dstr, "Event: ");
  380. dstr_append_str(&dstr, rls_get_package(s));
  381. dstr_append_zt(&dstr, "\r\n");
  382. dstr_append_zt(&dstr, "Require: eventlist\r\nContent-Type: ");
  383. dstr_append_str(&dstr, &content_type);
  384. dstr_append_zt(&dstr, "\r\n");
  385. res = dstr_get_str(&dstr, &headers);
  386. dstr_destroy(&dstr);
  387. if (res >= 0) {
  388. /* DEBUG("sending NOTIFY message to %.*s (subscription %p)\n",
  389. dlg->rem_uri.len,
  390. ZSW(dlg->rem_uri.s), s); */
  391. if (!is_str_empty(&doc)) body = doc;
  392. if (sm_subscription_terminated(&s->u.external) == 0) {
  393. /* doesn't matter if delivered or not, it will be freed otherwise !!! */
  394. res = tmb.t_request_within(&method, &headers, &body, dlg, 0, 0);
  395. if (res >= 0) clear_change_flags(s);
  396. }
  397. else {
  398. rls_notify_cb_param_t *cbd = create_notify_cb_param(s);
  399. if (!cbd) {
  400. ERR("Can't create notify cb data! Freeing RL subscription.\n");
  401. rls_remove(s); /* ?????? */
  402. removed = 1;
  403. res = -13;
  404. }
  405. else {
  406. /* the subscritpion will be destroyed if NOTIFY delivery problems */
  407. /* rls_unlock(); the callback locks this mutex ! */
  408. /* !!!! FIXME: callbacks can't be safely used (may be called or not,
  409. * may free memory automaticaly or not) !!! */
  410. res = tmb.t_request_within(&method, &headers, &body, dlg, rls_notify_cb, cbd);
  411. /* res = tmb.t_request_within(&method, &headers, &body, dlg, rls_notify_cb, s); */
  412. /* rls_lock(); the callback locks this mutex ! */
  413. if (res < 0) {
  414. /* does this mean, that the callback was not called ??? */
  415. ERR("t_request_within FAILED: %d! Freeing RL subscription.\n", res);
  416. rls_remove(s); /* ?????? */
  417. removed = 1;
  418. }
  419. else clear_change_flags(s);
  420. }
  421. }
  422. }
  423. if (doc.s) cds_free(doc.s);
  424. if (content_type.s) cds_free(content_type.s);
  425. if (headers.s) cds_free(headers.s);
  426. if ((!removed) && use_db) rls_db_update(s);
  427. if (res < 0) DEBUG("external notify NOT generated\n");
  428. else DEBUG("external notify generated\n");
  429. return res;
  430. }
  431. /* static raw_presence_info_t* rls2raw_presence_info(rl_subscription_t *s)
  432. {
  433. raw_presence_info_t *info;
  434. info = create_raw_presence_info(s->u.internal.record_id);
  435. if (!info) return info;
  436. str_clear(&info->pres_doc);
  437. str_clear(&info->content_type);
  438. DEBUG_LOG(" ... create RLMI document\n");
  439. create_rlmi_document(&info->pres_doc, &info->content_type, s, 1);
  440. return info;
  441. } */
  442. static int rls_generate_notify_int(rl_subscription_t *s, int full_info)
  443. {
  444. /* generate internal notification */
  445. str_t doc, content_type;
  446. /* TRACE("generating internal list notify\n"); */
  447. if (!s->u.internal.vs) return 1;
  448. DBG("generating internal rls notification\n");
  449. /* raw = rls2raw_presence_info(s); */
  450. if (create_rlmi_document(&doc, &content_type, s, full_info) < 0) {
  451. ERR("can't generate internal notification document\n");
  452. return -1;
  453. }
  454. clear_change_flags(s);
  455. /* documents are given to VS (we don't care about them
  456. * more - no free, ... */
  457. process_internal_notify(s->u.internal.vs,
  458. &doc, &content_type);
  459. return 0;
  460. }
  461. int rls_generate_notify(rl_subscription_t *s, int full_info)
  462. {
  463. /* !!! the main mutex must be locked here !!! */
  464. DBG("generating rls notification\n");
  465. if (!s) {
  466. ERR("called with <null> subscription\n");
  467. return -1;
  468. }
  469. switch (s->type) {
  470. case rls_external_subscription:
  471. return rls_generate_notify_ext(s, full_info);
  472. case rls_internal_subscription:
  473. return rls_generate_notify_int(s, full_info);
  474. }
  475. return -1;
  476. }
  477. int rls_prepare_subscription_response(rl_subscription_t *s, struct sip_msg *m) {
  478. /* char *hdr = "Supported: eventlist\r\n"; */
  479. char *hdr = "Require: eventlist\r\n";
  480. if (s->type != rls_external_subscription) return -1;
  481. if (!add_lump_rpl(m, hdr, strlen(hdr), LUMP_RPL_HDR)) return -1;
  482. return sm_prepare_subscription_response(rls_manager, &s->u.external, m);
  483. }
  484. /** returns the count of seconds remaining to subscription expiration */
  485. int rls_subscription_expires_in(rl_subscription_t *s)
  486. {
  487. if (s->type == rls_external_subscription)
  488. return sm_subscription_expires_in(rls_manager, &s->u.external);
  489. else return -1;
  490. }
  491. /* static str_t notifier_name = { s: "rls", len: 3 }; */
  492. /* static str_t pres_list_package = { s: "presence.list", len: 13 };
  493. int is_presence_list_package(const str_t *package)
  494. {
  495. return (str_case_equals(package, &pres_list_package) == 0);
  496. }*/
  497. int rls_create_internal_subscription(virtual_subscription_t *vs,
  498. rl_subscription_t **dst,
  499. flat_list_t *flat,
  500. int nesting_level)
  501. {
  502. rl_subscription_t *rls;
  503. /* try to make subscription and release it if internal subscription
  504. * not created */
  505. if (dst) *dst = NULL;
  506. rls = rls_alloc_subscription(rls_internal_subscription);
  507. if (!rls) {
  508. ERR("processing INTERNAL RLS subscription - memory allocation error\n");
  509. return -1;
  510. }
  511. rls->u.internal.record_id = &vs->uri; /* !!! NEVER !!! free this */
  512. rls->u.internal.package = rls_get_package(vs->subscription); /* !!! NEVER !!! free this */
  513. rls->u.internal.subscriber_id = rls_get_subscriber(vs->subscription); /* !!! NEVER !!! free this */
  514. rls->xcap_params = vs->subscription->xcap_params; /* !!! NEVER free this !!! */
  515. rls->u.internal.vs = vs;
  516. if (dst) *dst = rls;
  517. DBG("creating internal subscription to %.*s (VS %p)\n",
  518. FMT_STR(*rls->u.internal.record_id),
  519. rls->u.internal.vs);
  520. if (add_virtual_subscriptions(rls, flat, nesting_level) != 0) {
  521. rls_free(rls);
  522. if (dst) *dst = NULL;
  523. return -1;
  524. }
  525. rls_generate_notify(rls, 1);
  526. return 0;
  527. }