2
0

subscription_manager.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. #include "subscription_manager.h"
  2. #include "../../parser/parse_expires.h"
  3. #include "../../modules/tm/tm_load.h"
  4. #include "../../parser/hf.h"
  5. #include "../../parser/parse_from.h"
  6. #include "../../data_lump_rpl.h"
  7. #include <cds/dstring.h>
  8. #include <cds/logger.h>
  9. #include "result_codes.h"
  10. #include <presence/utils.h>
  11. static struct tm_binds tmb;
  12. /****** Functions for global initialization ******/
  13. int subscription_management_init(void)
  14. {
  15. load_tm_f load_tm;
  16. /* import the TM auto-loading function */
  17. if ( !(load_tm=(load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
  18. LOG(L_ERR, "subscription_management_init(): Can't import tm!\n");
  19. return -1;
  20. }
  21. /* let the auto-loading function load all TM stuff */
  22. if (load_tm(&tmb)==-1) {
  23. LOG(L_ERR, "subscription_management_init(): load_tm() failed\n");
  24. return -1;
  25. }
  26. return 0;
  27. }
  28. /****** Functions for standalone subscription manager manipulation ******/
  29. int sm_init(subscription_manager_t *sm,
  30. send_notify_func notify,
  31. terminate_func terminate,
  32. subscription_authorize_func authorize,
  33. gen_lock_t *mutex,
  34. int min_exp,
  35. int max_exp,
  36. int default_exp,
  37. int expiration_timer_period)
  38. {
  39. if (!sm) return -1;
  40. sm->first = NULL;
  41. sm->last = NULL;
  42. sm->notify = notify;
  43. sm->terminate = terminate;
  44. sm->authorize = authorize;
  45. sm->mutex = mutex;
  46. sm->default_expiration = default_exp;
  47. sm->min_expiration = min_exp;
  48. sm->max_expiration = max_exp;
  49. return tem_init(&sm->timer,
  50. expiration_timer_period, /* atomic time = 1 s */
  51. 4093, /* time slot count */
  52. 1, /* enable delay <= terminate AFTER the timeout */
  53. mutex);
  54. }
  55. subscription_manager_t *sm_create(send_notify_func notify,
  56. terminate_func terminate,
  57. subscription_authorize_func authorize,
  58. gen_lock_t *mutex,
  59. int min_exp,
  60. int max_exp,
  61. int default_exp,
  62. int expiration_timer_period)
  63. {
  64. subscription_manager_t *sm;
  65. sm = (subscription_manager_t*)mem_alloc(sizeof(subscription_manager_t));
  66. if (!sm) {
  67. LOG(L_ERR, "can't allocate subscription manager\n");
  68. return sm;
  69. }
  70. if (sm_init(sm, notify, terminate, authorize, mutex, min_exp,
  71. max_exp, default_exp, expiration_timer_period) != 0) {
  72. mem_free(sm);
  73. return NULL;
  74. }
  75. return sm;
  76. }
  77. void sm_add_subscription_nolock(subscription_manager_t *mng,
  78. subscription_data_t *s)
  79. {
  80. /* adds the subscription into the list of subscriptions */
  81. if (!s) return;
  82. s->next = NULL;
  83. s->prev = mng->last;
  84. if (mng->last) mng->last->next = s;
  85. else mng->first = s;
  86. mng->last = s;
  87. }
  88. void sm_remove_subscription_nolock(subscription_manager_t *mng,
  89. subscription_data_t *s)
  90. {
  91. /* removes the subscription from the list of subscriptions */
  92. if (s->prev) s->prev->next = s->next;
  93. else mng->first = s->next;
  94. if (s->next) s->next->prev = s->prev;
  95. else mng->last = s->prev;
  96. s->next = NULL;
  97. s->prev = NULL;
  98. }
  99. /****** Helper functions for subscription initialization ******/
  100. static int create_subscription_dialog(subscription_data_t *dst,
  101. struct sip_msg *m)
  102. {
  103. /* create SIP dialog for subscription */
  104. if (tmb.new_dlg_uas(m, 200, &dst->dialog) < 0) {
  105. LOG(L_ERR, "create_subscription_dialog(): Error while creating dialog.\n");
  106. return -1;
  107. }
  108. else {
  109. DEBUG_LOG("create_subscription_dialog(): new dialog created (%.*s, %.*s, %.*s)\n",
  110. dst->dialog->id.call_id.len, dst->dialog->id.call_id.s,
  111. dst->dialog->id.rem_tag.len, dst->dialog->id.rem_tag.s,
  112. dst->dialog->id.loc_tag.len, dst->dialog->id.loc_tag.s);
  113. }
  114. return 0;
  115. }
  116. static int get_subscription_expiration(subscription_manager_t *mng,
  117. struct sip_msg *m)
  118. {
  119. int e = 0;
  120. /* parse Expires header field */
  121. if (parse_headers(m, HDR_EXPIRES_T, 0) == -1) {
  122. LOG(L_ERR, "set_subscription_expiration(): Error while parsing headers\n");
  123. return RES_PARSE_HEADERS_ERR;
  124. }
  125. if (m->expires) {
  126. if (parse_expires(m->expires) < 0) {
  127. LOG(L_ERR, "set_subscription_expiration(): Error parsing Expires header\n");
  128. return RES_PARSE_HEADERS_ERR;
  129. }
  130. }
  131. e = mng->default_expiration;
  132. if (m->expires) {
  133. exp_body_t *expires = (exp_body_t *)m->expires->parsed;
  134. if (expires) if (expires->valid) e = expires->val;
  135. }
  136. if (e < 0) e = 0;
  137. if ((e != 0) && (e < mng->min_expiration)) {
  138. /* e = 0; */
  139. /*e = mng->min_expiration;*/
  140. /* Interval too short - must not be longer (RFC 3265) */
  141. LOG(L_ERR, "set_subscription_expiration(): interval too short (%d s)\n", e);
  142. return RES_EXPIRATION_INTERVAL_TOO_SHORT;
  143. }
  144. if (e > mng->max_expiration) e = mng->max_expiration;
  145. return e;
  146. }
  147. static void free_subscription_dialog(subscription_data_t *dst)
  148. {
  149. if (dst->dialog) tmb.free_dlg(dst->dialog);
  150. dst->dialog = NULL;
  151. }
  152. static int cmp_subscription(str_t *from_tag, str_t *to_tag, str_t *call_id,
  153. subscription_data_t *s)
  154. {
  155. /* LOG(L_TRACE, "comparing element dlg: %.*s, %.*s, %.*s\n",
  156. s->dialog->id.call_id.len, s->dialog->id.call_id.s,
  157. s->dialog->id.rem_tag.len, s->dialog->id.rem_tag.s,
  158. s->dialog->id.loc_tag.len, s->dialog->id.loc_tag.s);
  159. LOG(L_TRACE, "searching for: %.*s, %.*s, %.*s\n",
  160. call_id->len, call_id->s,
  161. from_tag->len, from_tag->s,
  162. to_tag->len, to_tag->s);
  163. */
  164. if (str_case_equals(call_id, &s->dialog->id.call_id) != 0) return 1;
  165. if (str_nocase_equals(from_tag, &s->dialog->id.rem_tag) != 0) return 1;
  166. if (str_nocase_equals(to_tag, &s->dialog->id.loc_tag) != 0) return 1;
  167. /* are the tags case sensitive? */
  168. return 0;
  169. }
  170. /* Get resource-list URI from SUBSCRIBE request */
  171. static int get_dst_uri(struct sip_msg* _m, str* dst_uri)
  172. {
  173. /* FIXME: get raw request URI? or from TO?
  174. * FIXME: skip uri parameters and everything else, leave only
  175. * sip:xxx@yyy ???!!! */
  176. str uri;
  177. if (_m->new_uri.s) {
  178. uri.s = _m->new_uri.s;
  179. uri.len = _m->new_uri.len;
  180. } else {
  181. uri.s = _m->first_line.u.request.uri.s;
  182. uri.len = _m->first_line.u.request.uri.len;
  183. }
  184. if (dst_uri) *dst_uri = uri;
  185. return RES_OK;
  186. }
  187. static inline int get_from_uri(struct sip_msg* _m, str* _u)
  188. {
  189. if (parse_from_header(_m) < 0) {
  190. LOG(L_ERR, "get_from_uri(): Error while parsing From body\n");
  191. return -1;
  192. }
  193. _u->s = ((struct to_body*)_m->from->parsed)->uri.s;
  194. _u->len = ((struct to_body*)_m->from->parsed)->uri.len;
  195. return 0;
  196. }
  197. /* Get subscriber's URI from SUBSCRIBE request */
  198. static int get_subscribers_uri(struct sip_msg* _m, str* dst_uri)
  199. {
  200. /* FIXME: skip uri parameters !!! */
  201. /* str uri; */
  202. str u;
  203. struct sip_uri s;
  204. if (!dst_uri) return RES_INTERNAL_ERR;
  205. if (parse_from_header(_m) < 0) {
  206. LOG(L_ERR, "get_subscribers_uri(): Error while parsing From header\n");
  207. return RES_PARSE_HEADERS_ERR;
  208. }
  209. u = ((struct to_body*)_m->from->parsed)->uri;
  210. if (parse_uri(u.s, u.len, &s) < 0) {
  211. LOG(L_ERR, "get_subscribers_uri(): Error while parsing From content\n");
  212. return RES_PARSE_HEADERS_ERR;
  213. }
  214. dst_uri->s = u.s;
  215. dst_uri->len = s.host.s + s.host.len - dst_uri->s;
  216. /*
  217. if (s.user.len > 0) uri.s = s.user.s;
  218. else uri.s = u.s;
  219. if (s.host.len <= 0) uri = u;
  220. else uri.len = s.host.s - uri.s + s.host.len;
  221. if (dst_uri) *dst_uri = uri;*/
  222. return RES_OK;
  223. }
  224. /* Get Event package from SUBSCRIBE request */
  225. static int get_package(struct sip_msg* m, str* dst)
  226. {
  227. dst->len = 0;
  228. dst->s = NULL;
  229. if ( (parse_headers(m, HDR_EVENT_T, 0) == -1) || (!m->event) ) {
  230. LOG(L_ERR, "get_package(): Error while parsing Event header\n");
  231. return RES_PARSE_HEADERS_ERR;
  232. }
  233. dst->s = m->event->body.s;
  234. dst->len = m->event->body.len;
  235. return RES_OK;
  236. }
  237. static int set_subscription_info(struct sip_msg *m, subscription_data_t *s)
  238. {
  239. str uri, subscriber_uri;
  240. str package;
  241. int r;
  242. /* get requested resource list URI */
  243. r = get_dst_uri(m, &uri);
  244. if (r != RES_OK) {
  245. LOG(L_ERR, "set_rls_info(): Can't decode resource list URI\n");
  246. return r;
  247. }
  248. /* get subscriber's URI */
  249. r = get_subscribers_uri(m, &subscriber_uri);
  250. if (r != RES_OK) {
  251. LOG(L_ERR, "set_rls_info(): Can't decode subscriber's URI\n");
  252. return r;
  253. }
  254. /* get event package */
  255. r = get_package(m, &package);
  256. if (r != RES_OK) {
  257. return r;
  258. }
  259. extract_server_contact(m, &s->contact, 0);
  260. DEBUG_LOG("set_subscription_info(): uri=\'%.*s\'\n", FMT_STR(uri));
  261. DEBUG_LOG("set_subscription_info(): package=\'%.*s\'\n", FMT_STR(package));
  262. DEBUG_LOG("set_subscription_info(): subscriber_uri=\'%.*s\'\n", FMT_STR(subscriber_uri));
  263. DEBUG_LOG("set_subscription_info(): contact=\'%.*s\'\n", FMT_STR(s->contact));
  264. r = str_dup(&s->record_id, &uri);
  265. if (r == 0) r = str_dup(&s->subscriber, &subscriber_uri);
  266. else str_clear(&s->subscriber);
  267. if (r == 0) r = str_dup(&s->package, &package);
  268. else str_clear(&s->package);
  269. return r;
  270. }
  271. static void free_subscription(subscription_data_t *s)
  272. {
  273. DEBUG_LOG("subscription manager: freeing subscription\n");
  274. str_free_content(&s->record_id);
  275. str_free_content(&s->package);
  276. str_free_content(&s->subscriber);
  277. str_free_content(&s->contact);
  278. free_subscription_dialog(s);
  279. }
  280. /****** Functions for standalone subscription manipulation ******/
  281. void subscription_expiration_cb(struct _time_event_data_t *ted)
  282. {
  283. /* the time event manager uses the same mutex and it is locked now ! */
  284. time_t t = time(NULL);
  285. subscription_manager_t *mng;
  286. subscription_data_t *s;
  287. mng = ted->cb_param1;
  288. s = ted->cb_param;
  289. DBG("subscription %p(%p) expired at: %s\n", s, mng, ctime(&t));
  290. if (mng && s) {
  291. if (s->status == subscription_pending)
  292. s->status = subscription_terminated_pending_to;
  293. else
  294. s->status = subscription_terminated_to;
  295. if (mng->notify) mng->notify(s);
  296. if (mng->terminate) mng->terminate(s);
  297. }
  298. }
  299. int sm_init_subscription_nolock(subscription_manager_t *mng,
  300. subscription_data_t *dst,
  301. struct sip_msg *m)
  302. {
  303. int e, res;
  304. authorization_result_t ares = auth_granted;
  305. if (!dst) return RES_INTERNAL_ERR;
  306. /* dst->usr_data = NULL; */ /* !!! do not initialize this - its user's and may be already initialized !!! */
  307. dst->prev = NULL;
  308. dst->next = NULL;
  309. dst->dialog = NULL;
  310. dst->contact.s = NULL;
  311. dst->contact.len = 0;
  312. dst->status = subscription_uninitialized;
  313. str_clear(&dst->record_id);
  314. str_clear(&dst->subscriber);
  315. str_clear(&dst->package);
  316. /* fill time event structure */
  317. dst->expiration.cb = subscription_expiration_cb;
  318. dst->expiration.cb_param = dst;
  319. dst->expiration.cb_param1 = mng;
  320. res = set_subscription_info(m, dst);
  321. if (res != RES_OK) {
  322. free_subscription(dst);
  323. return res;
  324. }
  325. create_subscription_dialog(dst, m);
  326. if (mng->authorize) ares = mng->authorize(dst);
  327. switch (ares) {
  328. case auth_granted:
  329. dst->status = subscription_active;
  330. break;
  331. case auth_polite_block:
  332. LOG(L_WARN, "polite blocking not implemented - marking subscription as rejected!\n");
  333. /* other possibility is to give it to pending state, but this eats resources */
  334. dst->status = subscription_terminated;
  335. return RES_SUBSCRIPTION_REJECTED;
  336. case auth_rejected:
  337. dst->status = subscription_terminated;
  338. return RES_SUBSCRIPTION_REJECTED;
  339. case auth_unresolved:
  340. dst->status = subscription_pending;
  341. break;
  342. }
  343. /* set expiration timeout from min, max, default and Expires header field */
  344. e = get_subscription_expiration(mng, m);
  345. if (e < 0) {
  346. free_subscription(dst);
  347. return e; /* it contains the error number */
  348. }
  349. /* add this subscription to the list of subscriptions */
  350. sm_add_subscription_nolock(mng, dst);
  351. /* FIXME - bug? - add if e == 0 too? */
  352. if (e > 0) {
  353. /* start timeout timer for this subscription */
  354. tem_add_event_nolock(&mng->timer, e, &dst->expiration);
  355. DEBUG_LOG("subscription will expire in %d s\n", e);
  356. }
  357. else { /* polling */
  358. if (dst->status == subscription_pending)
  359. dst->status = subscription_terminated_pending;
  360. else
  361. dst->status = subscription_terminated;
  362. }
  363. return RES_OK;
  364. }
  365. int sm_init_subscription_nolock_ex(subscription_manager_t *mng,
  366. subscription_data_t *dst,
  367. dlg_t *dialog,
  368. subscription_status_t status,
  369. const str_t *contact,
  370. const str_t *record_id,
  371. const str_t *package,
  372. const str_t *subscriber,
  373. int expires_after,
  374. void *subscription_data)
  375. {
  376. int r = 0;
  377. if (!dst) return RES_INTERNAL_ERR;
  378. dst->usr_data = subscription_data;
  379. dst->prev = NULL;
  380. dst->next = NULL;
  381. dst->dialog = dialog;
  382. r = str_dup(&dst->contact, contact);
  383. dst->status = status;
  384. if (r == 0) r = str_dup(&dst->record_id, record_id);
  385. else str_clear(&dst->record_id);
  386. if (r == 0) r = str_dup(&dst->subscriber, subscriber);
  387. else str_clear(&dst->subscriber);
  388. if (r == 0) r = str_dup(&dst->package, package);
  389. else str_clear(&dst->package);
  390. /* fill time event structure */
  391. dst->expiration.cb = subscription_expiration_cb;
  392. dst->expiration.cb_param = dst;
  393. dst->expiration.cb_param1 = mng;
  394. DEBUG_LOG("uri=\'%.*s\'\n", FMT_STR(dst->record_id));
  395. DEBUG_LOG("package=\'%.*s\'\n", FMT_STR(dst->package));
  396. DEBUG_LOG("subscriber_uri=\'%.*s\'\n", FMT_STR(dst->subscriber));
  397. DEBUG_LOG("contact=\'%.*s\'\n", FMT_STR(dst->contact));
  398. /* set expiration timeout from min, max, default and Expires header field */
  399. if (expires_after < 0) expires_after = 0;
  400. if (expires_after > 0) {
  401. /* start timeout timer for this subscription */
  402. tem_add_event_nolock(&mng->timer, expires_after, &dst->expiration);
  403. DEBUG_LOG("subscription will expire in %d s\n", expires_after);
  404. }
  405. else { /* polling */
  406. if (dst->status == subscription_pending)
  407. dst->status = subscription_terminated_pending;
  408. else
  409. dst->status = subscription_terminated;
  410. }
  411. /* add this subscription to the list of subscriptions */
  412. sm_add_subscription_nolock(mng, dst);
  413. /* FIXME - bug? - add if e == 0 too? */
  414. return r;
  415. }
  416. int sm_refresh_subscription_nolock(subscription_manager_t *mng,
  417. subscription_data_t *s,
  418. struct sip_msg *m)
  419. {
  420. int e;
  421. if (!s) return RES_INTERNAL_ERR;
  422. /* refresh SIP dialog */
  423. if (s->dialog) tmb.dlg_request_uas(s->dialog, m, IS_TARGET_REFRESH);
  424. if (sm_subscription_terminated(s) != 0) { /* not terminated */
  425. tem_remove_event_nolock(&mng->timer, &s->expiration);
  426. }
  427. else return RES_SUBSCRIPTION_TERMINATED;
  428. /* fill time event structure */
  429. s->expiration.cb = subscription_expiration_cb;
  430. s->expiration.cb_param = s;
  431. s->expiration.cb_param1 = mng;
  432. /* set expiration timeout from min, max, default and Expires header field */
  433. e = get_subscription_expiration(mng, m);
  434. if (e < 0) return e; /* it contains the error number */
  435. if (e == 0) { /* unsubscribe */
  436. if (s->status == subscription_pending)
  437. s->status = subscription_terminated_pending;
  438. else
  439. s->status = subscription_terminated;
  440. }
  441. else {
  442. /* start timeout timer for this subscription */
  443. tem_add_event_nolock(&mng->timer, e, &s->expiration);
  444. DEBUG_LOG("subscription refreshed, will expire in %d s\n", e);
  445. }
  446. return RES_OK;
  447. }
  448. void sm_release_subscription_nolock(subscription_manager_t *mng,
  449. subscription_data_t *dst)
  450. {
  451. if (!dst) return;
  452. if (dst->status == subscription_uninitialized) return;
  453. if (sm_subscription_terminated(dst) != 0) { /* NOT terminated */
  454. /* remove timeout timer */
  455. tem_remove_event_nolock(&mng->timer, &dst->expiration);
  456. }
  457. /* remove this subscription from the list */
  458. sm_remove_subscription_nolock(mng, dst);
  459. free_subscription(dst);
  460. }
  461. int sm_prepare_subscription_response(subscription_manager_t *mng,
  462. subscription_data_t *s,
  463. struct sip_msg *m)
  464. {
  465. char tmp[64];
  466. int t = 0;
  467. if (s->contact.len > 0) {
  468. if (!add_lump_rpl(m, s->contact.s, s->contact.len, LUMP_RPL_HDR)) {
  469. LOG(L_ERR, "sm_prepare_subscription_response(): Can't add Contact header to the response\n");
  470. return -1;
  471. }
  472. }
  473. t = sm_subscription_expires_in(mng, s);
  474. sprintf(tmp, "Expires: %d\r\n", t);
  475. if (!add_lump_rpl(m, tmp, strlen(tmp), LUMP_RPL_HDR)) {
  476. LOG(L_ERR, "sm_prepare_subscription_response(): Can't add Expires header to the response\n");
  477. return -1;
  478. }
  479. return 0;
  480. }
  481. int sm_subscription_expires_in(subscription_manager_t *mng,
  482. subscription_data_t *s)
  483. {
  484. int t = 0;
  485. if (sm_subscription_terminated(s) != 0) /* NOT terminated */
  486. t = (s->expiration.tick_time - mng->timer.tick_counter) * mng->timer.atomic_time;
  487. return t;
  488. }
  489. int sm_find_subscription(subscription_manager_t *mng,
  490. str_t *from_tag, str_t *to_tag, str_t *call_id,
  491. subscription_data_t **dst)
  492. {
  493. subscription_data_t *e;
  494. /* FIXME: use hash table or something like that ! */
  495. *dst = NULL;
  496. e = mng->first;
  497. while (e) {
  498. if (cmp_subscription(from_tag, to_tag, call_id, e) == 0) {
  499. *dst = e;
  500. return RES_OK;
  501. }
  502. e = e->next;
  503. }
  504. return RES_NOT_FOUND;
  505. }
  506. int sm_subscription_terminated(subscription_data_t *s)
  507. {
  508. if (!s) return 0;
  509. if (s->status == subscription_terminated) return 0;
  510. if (s->status == subscription_terminated_to) return 0;
  511. if (s->status == subscription_terminated_pending) return 0;
  512. if (s->status == subscription_terminated_pending_to) return 0;
  513. return 1; /* 1 means NOT terminated ! */
  514. }
  515. int sm_subscription_pending(subscription_data_t *s)
  516. {
  517. if (!s) return 0;
  518. if (s->status == subscription_pending) return 0;
  519. if (s->status == subscription_terminated_pending) return 0;
  520. if (s->status == subscription_terminated_pending_to) return 0;
  521. return 1; /* 1 means NOT pending ! */
  522. }