pres_timer.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #include "presentity.h"
  2. #include "pa_mod.h"
  3. #include "ptime.h"
  4. #include "notify.h"
  5. #include "async_auth.h"
  6. #include "tuple.h"
  7. #include "pres_notes.h"
  8. #include "extension_elements.h"
  9. static void process_watchers(presentity_t* _p, int *changed)
  10. {
  11. watcher_t *next, *w;
  12. int presentity_changed;
  13. int notify;
  14. /* !!! "changed" is not initialized here it is only set if change
  15. * in presentity occurs */
  16. presentity_changed = _p->flags & PFLAG_PRESENCE_CHANGED;
  17. w = _p->first_watcher;
  18. while (w) {
  19. /* changes status of expired watcher */
  20. if (w->expires <= act_time) {
  21. LOG(L_DBG, "Expired watcher %.*s\n", w->uri.len, w->uri.s);
  22. w->expires = 0;
  23. set_watcher_terminated_status(w);
  24. _p->flags |= PFLAG_WATCHERINFO_CHANGED;
  25. w->flags |= WFLAG_SUBSCRIPTION_CHANGED;
  26. if (changed) *changed = 1;
  27. }
  28. /* send NOTIFY if needed */
  29. notify = 0;
  30. if ((w->flags & WFLAG_SUBSCRIPTION_CHANGED)) {
  31. notify = 1;
  32. if (changed) *changed = 1; /* ??? */
  33. }
  34. if (presentity_changed && is_watcher_authorized(w)) notify = 1;
  35. if (notify) send_notify(_p, w);
  36. w->flags &= ~WFLAG_SUBSCRIPTION_CHANGED;
  37. if (is_watcher_terminated(w)) {
  38. next = w->next;
  39. remove_watcher(_p, w);
  40. free_watcher(w);
  41. w = next;
  42. if (changed) *changed = 1;
  43. }
  44. else w = w->next;
  45. }
  46. }
  47. static void process_winfo_watchers(presentity_t* _p, int *changed)
  48. {
  49. watcher_t *next, *w;
  50. int notify;
  51. /* !!! "changed" is not initialized here it is only set if change
  52. * in presentity occurs */
  53. w = _p->first_winfo_watcher;
  54. while (w) {
  55. /* changes status of expired watcher */
  56. if (w->expires <= act_time) {
  57. LOG(L_DBG, "Expired watcher %.*s\n", w->uri.len, w->uri.s);
  58. w->expires = 0;
  59. set_watcher_terminated_status(w);
  60. w->flags |= WFLAG_SUBSCRIPTION_CHANGED;
  61. if (changed) *changed = 1;
  62. }
  63. /* send NOTIFY if needed */
  64. notify = 0;
  65. if ((w->flags & WFLAG_SUBSCRIPTION_CHANGED)) {
  66. notify = 1;
  67. if (changed) *changed = 1; /* ??? */
  68. }
  69. if ((_p->flags & PFLAG_WATCHERINFO_CHANGED) &&
  70. is_watcher_authorized(w)) notify = 1;
  71. if (notify) send_notify(_p, w);
  72. w->flags &= ~WFLAG_SUBSCRIPTION_CHANGED;
  73. if (is_watcher_terminated(w)) {
  74. next = w->next;
  75. remove_watcher(_p, w);
  76. free_watcher(w);
  77. w = next;
  78. if (changed) *changed = 1;
  79. }
  80. else w = w->next;
  81. }
  82. }
  83. /* static void mark_expired_tuples(presentity_t *_p, int *changed)
  84. {
  85. presence_tuple_t *t;
  86. t = _p->tuples;
  87. while (t) {
  88. if (t->expires < act_time) {
  89. t->state = PS_OFFLINE;
  90. if (changed) *changed = 1;
  91. _p->flags |= PFLAG_PRESENCE_CHANGED;
  92. }
  93. t = t->next;
  94. }
  95. }*/
  96. static void remove_expired_tuples(presentity_t *_p, int *changed)
  97. {
  98. presence_tuple_t *t, *n;
  99. t = (presence_tuple_t*)_p->data.first_tuple;
  100. while (t) {
  101. n = (presence_tuple_t *)t->data.next;
  102. if (t->expires < act_time) {
  103. DBG("Expiring tuple %.*s\n", t->data.contact.len, t->data.contact.s);
  104. remove_presence_tuple(_p, t);
  105. free_presence_tuple(t);
  106. if (changed) *changed = 1;
  107. _p->flags |= PFLAG_PRESENCE_CHANGED;
  108. }
  109. t = n;
  110. }
  111. }
  112. static void remove_expired_notes(presentity_t *_p)
  113. {
  114. pa_presence_note_t *n, *nn;
  115. n = (pa_presence_note_t*)_p->data.first_note;
  116. while (n) {
  117. nn = (pa_presence_note_t *)n->data.next;
  118. if (n->expires < act_time) {
  119. DBG("Expiring note %.*s\n", FMT_STR(n->data.value));
  120. remove_pres_note(_p, n);
  121. _p->flags |= PFLAG_PRESENCE_CHANGED;
  122. }
  123. n = nn;
  124. }
  125. }
  126. static void remove_expired_extension_elements(presentity_t *_p)
  127. {
  128. pa_extension_element_t *n, *nn;
  129. n = (pa_extension_element_t *)_p->data.first_unknown_element;
  130. while (n) {
  131. nn = (pa_extension_element_t *)n->data.next;
  132. if (n->expires < act_time) {
  133. DBG("Expiring person element %.*s\n", FMT_STR(n->dbid));
  134. remove_extension_element(_p, n);
  135. _p->flags |= PFLAG_PRESENCE_CHANGED;
  136. }
  137. n = nn;
  138. }
  139. }
  140. static inline int refresh_auth_rules(presentity_t *p)
  141. {
  142. /* TODO reload authorization rules if needed */
  143. if ((p->auth_rules_refresh_time > 0) &&
  144. (p->auth_rules_refresh_time <= act_time)) {
  145. /* INFO("refreshing auth rules\n"); */
  146. ask_auth_rules(p); /* it will run next time if fails now */
  147. p->auth_rules_refresh_time = act_time + auth_rules_refresh_time;
  148. }
  149. return 0;
  150. }
  151. static void process_tuple_change(presentity_t *p, tuple_change_info_t *info)
  152. {
  153. presence_tuple_t *tuple = NULL;
  154. basic_tuple_status_t orig;
  155. time_t e;
  156. DBG("processing tuple change message: %.*s, %.*s, %d\n",
  157. FMT_STR(info->user), FMT_STR(info->contact), info->state);
  158. if (is_str_empty(&info->contact)) {
  159. /* error - registered tuples need contact address */
  160. ERR("invalid registered tuple (empty contact)\n");
  161. return;
  162. }
  163. if (info->state == presence_tuple_closed) {
  164. e = act_time + 2 * timer_interval;
  165. }
  166. else {
  167. e = INT_MAX; /* act_time + default_expires; */
  168. /* hack - re-registrations don't call the callback */
  169. }
  170. /* Find only registered (not published) tuple - don't overwrite
  171. * published information! */
  172. if (find_registered_presence_tuple(&info->contact, p, &tuple) != 0) {
  173. /* not found -> create new tuple */
  174. new_presence_tuple(&info->contact, e, &tuple, 0, NULL, NULL, NULL);
  175. if (!tuple) return; /* error */
  176. tuple->data.status.basic = info->state;
  177. add_presence_tuple(p, tuple);
  178. p->flags |= PFLAG_PRESENCE_CHANGED;
  179. }
  180. else {
  181. /* tuple found -> update */
  182. orig = tuple->data.status.basic;
  183. tuple->data.status.basic = info->state;
  184. tuple->expires = e;
  185. db_update_presence_tuple(p, tuple, 0);
  186. if (orig != tuple->data.status.basic) p->flags |= PFLAG_PRESENCE_CHANGED;
  187. }
  188. }
  189. static int process_qsa_message(presentity_t *p, client_notify_info_t *info)
  190. {
  191. TRACE("received QSA notification for presentity %.*s\n", FMT_STR(p->data.uri));
  192. /* TODO: handle it as publish for special tuple (but handle merging
  193. * from multiple QSA sources in any way) */
  194. return 0;
  195. }
  196. static void process_presentity_messages(presentity_t *p)
  197. {
  198. mq_message_t *msg;
  199. tuple_change_info_t *info;
  200. client_notify_info_t *qsa_info;
  201. while ((msg = pop_message(&p->mq)) != NULL) {
  202. /* FIXME: ugly data type detection */
  203. if (msg->destroy_function == (destroy_function_f)free_tuple_change_info_content) {
  204. info = (tuple_change_info_t*)get_message_data(msg);
  205. if (info) process_tuple_change(p, info);
  206. }
  207. else {
  208. /* QSA message */
  209. qsa_info = (client_notify_info_t *)get_message_data(msg);
  210. if (qsa_info) process_qsa_message(p, qsa_info);
  211. }
  212. free_message(msg);
  213. }
  214. }
  215. int timer_presentity(presentity_t* _p)
  216. {
  217. int old_flags;
  218. int presentity_changed;
  219. PROF_START(pa_timer_presentity)
  220. old_flags = _p->flags;
  221. /* reload authorization rules if needed */
  222. refresh_auth_rules(_p);
  223. process_presentity_messages(_p);
  224. remove_expired_tuples(_p, NULL);
  225. remove_expired_notes(_p);
  226. remove_expired_extension_elements(_p);
  227. /* notify watchers and remove expired */
  228. process_watchers(_p, NULL);
  229. /* notify winfo watchers and remove expired */
  230. process_winfo_watchers(_p, NULL);
  231. /* notify internal watchers */
  232. presentity_changed = _p->flags & PFLAG_PRESENCE_CHANGED;
  233. if (presentity_changed) {
  234. /* DBG("presentity %.*s changed\n", _p->uri.len, _p->uri.s); */
  235. notify_qsa_watchers(_p);
  236. }
  237. /* clear presentity "change" flags */
  238. _p->flags &= ~(PFLAG_PRESENCE_CHANGED | PFLAG_WATCHERINFO_CHANGED);
  239. /* update DB record if something changed - USELESS */
  240. /* if (changed) {
  241. db_update_presentity(_p);
  242. }
  243. */
  244. PROF_STOP(pa_timer_presentity)
  245. return 0;
  246. }