tuple.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. #include "presentity.h"
  2. #include <cds/dbid.h>
  3. #include "paerrno.h"
  4. #include "pa_mod.h"
  5. #include "tuple.h"
  6. #include "tuple_notes.h"
  7. #include "tuple_extensions.h"
  8. void add_presence_tuple_no_wb(presentity_t *_p, presence_tuple_t *_t);
  9. /*
  10. * Create a new presence_tuple
  11. */
  12. int new_presence_tuple(str* _contact, time_t expires,
  13. presence_tuple_t ** _t, int is_published, str *id,
  14. str *published_id, str *etag)
  15. {
  16. presence_tuple_t* tuple;
  17. int size = 0;
  18. int len;
  19. dbid_t tmp;
  20. if (!_t) {
  21. paerrno = PA_INTERNAL_ERROR;
  22. ERR("Invalid parameter value\n");
  23. return -1;
  24. }
  25. if (!id) {
  26. /* always needed (for PIDF documents, ...) */
  27. generate_dbid(tmp);
  28. len = dbid_strlen(tmp);
  29. }
  30. else len = id->len;
  31. size = sizeof(presence_tuple_t);
  32. if (etag) size += etag->len;
  33. if (published_id) size += published_id->len;
  34. if (!is_published) {
  35. if (_contact) size += _contact->len;
  36. /* Non-published tuples have contact allocated
  37. * together with other data! */
  38. }
  39. size += len;
  40. tuple = (presence_tuple_t*)mem_alloc(size);
  41. if (!tuple) {
  42. paerrno = PA_NO_MEMORY;
  43. ERR("No memory left: size=%d\n", size);
  44. return -1;
  45. }
  46. memset(tuple, 0, sizeof(presence_tuple_t));
  47. tuple->data.status.basic = presence_tuple_undefined_status;
  48. tuple->data.id.s = ((char*)tuple) + sizeof(presence_tuple_t);
  49. if (id) str_cpy(&tuple->data.id, id);
  50. else dbid_strcpy(&tuple->data.id, tmp, len);
  51. tuple->etag.s = after_str_ptr(&tuple->data.id);
  52. if (etag) str_cpy(&tuple->etag, etag);
  53. else tuple->etag.len = 0;
  54. tuple->published_id.s = after_str_ptr(&tuple->etag);
  55. if (published_id) str_cpy(&tuple->published_id, published_id);
  56. else tuple->published_id.len = 0;
  57. if (is_published) {
  58. str_dup(&tuple->data.contact, _contact);
  59. /* published contacts can change */
  60. }
  61. else {
  62. /* non-published contacts can NOT change !!! */
  63. tuple->data.contact.s = after_str_ptr(&tuple->published_id);
  64. if (_contact) str_cpy(&tuple->data.contact, _contact);
  65. else tuple->data.contact.len = 0;
  66. }
  67. tuple->expires = expires;
  68. tuple->data.priority = default_priority;
  69. tuple->is_published = is_published;
  70. *_t = tuple;
  71. return 0;
  72. }
  73. int db_read_tuples(presentity_t *_p, db_con_t* db)
  74. {
  75. db_key_t keys[] = { col_pres_id };
  76. db_op_t ops[] = { OP_EQ };
  77. db_val_t k_vals[] = { { DB_STR, 0, { .str_val = _p->pres_id } } };
  78. int i;
  79. int r = 0;
  80. db_res_t *res = NULL;
  81. db_key_t result_cols[] = { col_basic, col_expires, col_priority,
  82. col_contact, col_tupleid, col_etag,
  83. col_published_id
  84. } ;
  85. if (!use_db) return 0;
  86. if (pa_dbf.use_table(db, presentity_contact_table) < 0) {
  87. ERR("Error in use_table\n");
  88. return -1;
  89. }
  90. if (pa_dbf.query (db, keys, ops, k_vals,
  91. result_cols, 1, sizeof(result_cols) / sizeof(db_key_t),
  92. 0, &res) < 0) {
  93. ERR("Error while querying DB\n");
  94. return -1;
  95. }
  96. if (!res) return 0; /* ? */
  97. for (i = 0; i < res->n; i++) {
  98. presence_tuple_t *tuple = NULL;
  99. db_row_t *row = &res->rows[i];
  100. db_val_t *row_vals = ROW_VALUES(row);
  101. str contact = STR_NULL;
  102. basic_tuple_status_t basic = presence_tuple_undefined_status;
  103. str id = STR_NULL;
  104. str etag = STR_NULL;
  105. str published_id = STR_NULL;
  106. time_t expires = 0;
  107. double priority = row_vals[2].val.double_val;
  108. #define get_str_val(i,dst) do{if(!row_vals[i].nul){dst.s=(char*)row_vals[i].val.string_val;dst.len=strlen(dst.s);}}while(0)
  109. #define get_int_val(i,dst) do{if(!row_vals[i].nul){dst=row_vals[i].val.int_val;}}while(0)
  110. #define get_time_val(i,dst) do{if(!row_vals[i].nul){dst=row_vals[i].val.time_val;}}while(0)
  111. get_int_val(0, basic);
  112. get_time_val(1, expires);
  113. get_str_val(3, contact);
  114. get_str_val(4, id);
  115. get_str_val(5, etag);
  116. get_str_val(6, published_id);
  117. #undef get_str_val
  118. #undef get_time_val
  119. r = new_presence_tuple(&contact, expires, &tuple, 1, &id,
  120. &published_id, &etag) | r;
  121. if (tuple) {
  122. tuple->data.status.basic = basic;
  123. LOG(L_DBG, "read tuple %.*s\n", id.len, id.s);
  124. tuple->data.priority = priority;
  125. db_read_tuple_notes(_p, tuple, db);
  126. db_read_tuple_extensions(_p, tuple, db);
  127. add_presence_tuple_no_wb(_p, tuple);
  128. }
  129. }
  130. pa_dbf.free_result(db, res);
  131. return r;
  132. }
  133. static int set_tuple_db_data(presentity_t *_p, presence_tuple_t *tuple,
  134. db_key_t *cols, db_val_t *vals, int *col_cnt)
  135. {
  136. int n_updates = 0;
  137. cols[n_updates] = col_tupleid;
  138. vals[n_updates].type = DB_STR;
  139. vals[n_updates].nul = 0;
  140. vals[n_updates].val.str_val = tuple->data.id;
  141. n_updates++;
  142. cols[n_updates] = col_pres_id;
  143. vals[n_updates].type = DB_STR;
  144. vals[n_updates].nul = 0;
  145. vals[n_updates].val.str_val = _p->pres_id;
  146. n_updates++;
  147. cols[n_updates] = col_basic;
  148. vals[n_updates].type = DB_INT;
  149. vals[n_updates].nul = 0;
  150. vals[n_updates].val.int_val = tuple->data.status.basic;
  151. n_updates++;
  152. cols[n_updates] = col_contact;
  153. vals[n_updates].type = DB_STR;
  154. vals[n_updates].nul = 0;
  155. vals[n_updates].val.str_val = tuple->data.contact;
  156. n_updates++;
  157. cols[n_updates] = col_etag;
  158. vals[n_updates].type = DB_STR;
  159. vals[n_updates].nul = 0;
  160. vals[n_updates].val.str_val = tuple->etag;
  161. n_updates++;
  162. cols[n_updates] = col_published_id;
  163. vals[n_updates].type = DB_STR;
  164. vals[n_updates].nul = 0;
  165. vals[n_updates].val.str_val = tuple->published_id;
  166. n_updates++;
  167. if (tuple->data.priority != 0.0) {
  168. cols[n_updates] = col_priority;
  169. vals[n_updates].type = DB_DOUBLE;
  170. vals[n_updates].nul = 0;
  171. vals[n_updates].val.double_val = tuple->data.priority;
  172. n_updates++;
  173. }
  174. if (tuple->expires != 0) {
  175. cols[n_updates] = col_expires;
  176. vals[n_updates].type = DB_DATETIME;
  177. vals[n_updates].nul = 0;
  178. vals[n_updates].val.time_val = tuple->expires;
  179. n_updates++;
  180. }
  181. *col_cnt = n_updates;
  182. return 0;
  183. }
  184. static int db_add_presence_tuple(presentity_t *_p, presence_tuple_t *t)
  185. {
  186. db_key_t query_cols[20];
  187. db_val_t query_vals[20];
  188. int n_query_cols = 0;
  189. int res;
  190. if (!use_db) return 0;
  191. if (!t->is_published) return 0; /* store only published tuples */
  192. if (set_tuple_db_data(_p, t, query_cols,
  193. query_vals, &n_query_cols) != 0) {
  194. return -1;
  195. }
  196. if (pa_dbf.use_table(pa_db, presentity_contact_table) < 0) {
  197. LOG(L_ERR, "db_add_presence_tuple: Error in use_table\n");
  198. return -1;
  199. }
  200. if (pa_dbf.insert(pa_db, query_cols, query_vals, n_query_cols) < 0) {
  201. LOG(L_ERR, "db_add_presence_tuple: Can't insert record\n");
  202. return -1;
  203. }
  204. res = 0;
  205. if (db_add_tuple_notes(_p, t) < 0) {
  206. res = -2;
  207. ERR("can't add tuple notes into DB\n");
  208. }
  209. if (db_add_tuple_extensions(_p, t) < 0) {
  210. res = -3;
  211. ERR("can't add tuple extensions into DB\n");
  212. }
  213. return res;
  214. }
  215. static int db_remove_presence_tuple(presentity_t *_p, presence_tuple_t *t)
  216. {
  217. db_key_t keys[] = { col_pres_id, col_tupleid };
  218. db_op_t ops[] = { OP_EQ, OP_EQ };
  219. db_val_t k_vals[] = { { DB_STR, 0, { .str_val = _p->pres_id } },
  220. { DB_STR, 0, { .str_val = t->data.id } } };
  221. if (!use_db) return 0;
  222. if (!t->is_published) return 0; /* store only published tuples */
  223. db_remove_tuple_notes(_p, t);
  224. db_remove_tuple_extensions(_p, t);
  225. if (pa_dbf.use_table(pa_db, presentity_contact_table) < 0) {
  226. LOG(L_ERR, "db_remove_presence_tuple: Error in use_table\n");
  227. return -1;
  228. }
  229. if (pa_dbf.delete(pa_db, keys, ops, k_vals, 2) < 0) {
  230. LOG(L_ERR, "db_remove_presence_tuple: Can't delete record\n");
  231. return -1;
  232. }
  233. return 0;
  234. }
  235. int db_update_presence_tuple(presentity_t *_p, presence_tuple_t *t, int update_notes_and_ext)
  236. {
  237. db_key_t keys[] = { col_pres_id, col_tupleid };
  238. db_op_t ops[] = { OP_EQ, OP_EQ };
  239. db_val_t k_vals[] = { { DB_STR, 0, { .str_val = _p->pres_id } },
  240. { DB_STR, 0, { .str_val = t->data.id } } };
  241. db_key_t query_cols[20];
  242. db_val_t query_vals[20];
  243. int n_query_cols = 0;
  244. if (!use_db) return 0;
  245. if (!t->is_published) return 0; /* store only published tuples */
  246. if (set_tuple_db_data(_p, t, query_cols,
  247. query_vals, &n_query_cols) != 0) {
  248. return -1;
  249. }
  250. if (pa_dbf.use_table(pa_db, presentity_contact_table) < 0) {
  251. ERR("Error in use_table\n");
  252. return -1;
  253. }
  254. if (pa_dbf.update(pa_db, keys, ops, k_vals,
  255. query_cols, query_vals, 2, n_query_cols) < 0) {
  256. ERR("Can't update record\n");
  257. return -1;
  258. }
  259. if (update_notes_and_ext) {
  260. db_update_tuple_notes(_p, t);
  261. db_update_tuple_extensions(_p, t);
  262. }
  263. return 0;
  264. }
  265. void add_presence_tuple_no_wb(presentity_t *_p, presence_tuple_t *_t)
  266. {
  267. DOUBLE_LINKED_LIST_ADD(_p->data.first_tuple,
  268. _p->data.last_tuple, (presence_tuple_info_t*)_t);
  269. }
  270. void add_presence_tuple(presentity_t *_p, presence_tuple_t *_t)
  271. {
  272. add_presence_tuple_no_wb(_p, _t);
  273. if (use_db) db_add_presence_tuple(_p, _t);
  274. }
  275. void remove_presence_tuple(presentity_t *_p, presence_tuple_t *_t)
  276. {
  277. DOUBLE_LINKED_LIST_REMOVE(_p->data.first_tuple,
  278. _p->data.last_tuple, (presence_tuple_info_t*)_t);
  279. if (use_db) db_remove_presence_tuple(_p, _t);
  280. }
  281. /*
  282. * Free all memory associated with a presence_tuple
  283. */
  284. void free_presence_tuple(presence_tuple_t * _t)
  285. {
  286. if (_t) {
  287. free_tuple_notes(_t);
  288. free_tuple_extensions(_t);
  289. if (_t->is_published) {
  290. /* Warning: not-published tuples have contact allocated
  291. * together with other data => contact can't change! */
  292. str_free_content(&_t->data.contact);
  293. }
  294. mem_free(_t);
  295. }
  296. }
  297. /*
  298. * Find a presence_tuple for contact _contact on presentity _p
  299. */
  300. int find_registered_presence_tuple(str* _contact, presentity_t *_p, presence_tuple_t ** _t)
  301. {
  302. presence_tuple_t *tuple;
  303. if (!_contact || !_contact->len || !_p || !_t) {
  304. paerrno = PA_INTERNAL_ERROR;
  305. LOG(L_ERR, "find_presence_tuple(): Invalid parameter value\n");
  306. return -1;
  307. }
  308. tuple = get_first_tuple(_p);
  309. while (tuple) {
  310. /* only contacts from usrloc should have unique contact - published
  311. * may be more times !!! */
  312. if (!tuple->is_published) {
  313. if (str_nocase_equals(&tuple->data.contact, _contact) == 0) {
  314. *_t = tuple;
  315. return 0;
  316. }
  317. }
  318. tuple = (presence_tuple_t*)tuple->data.next;
  319. }
  320. return 1;
  321. }
  322. /*
  323. * Find a presence_tuple on presentity _p
  324. */
  325. int find_presence_tuple_id(str* id, presentity_t *_p, presence_tuple_t ** _t)
  326. {
  327. presence_tuple_t *tuple;
  328. if (!id || !id->len || !_p || !_t) {
  329. paerrno = PA_INTERNAL_ERROR;
  330. LOG(L_ERR, "find_presence_tuple_id(): Invalid parameter value\n");
  331. return -1;
  332. }
  333. tuple = get_first_tuple(_p);
  334. while (tuple) {
  335. if (str_case_equals(&tuple->data.id, id) == 0) {
  336. *_t = tuple;
  337. return 0;
  338. }
  339. tuple = (presence_tuple_t*)tuple->data.next;
  340. }
  341. return 1;
  342. }
  343. presence_tuple_t *find_published_tuple(presentity_t *presentity, str *etag, str *id)
  344. {
  345. presence_tuple_t *tuple = get_first_tuple(presentity);
  346. while (tuple) {
  347. if (str_case_equals(&tuple->etag, etag) == 0) {
  348. if (str_case_equals(&tuple->published_id, id) == 0)
  349. return tuple;
  350. }
  351. tuple = get_next_tuple(tuple);
  352. }
  353. return NULL;
  354. }
  355. static inline void dup_tuple_notes(presence_tuple_t *dst, presence_tuple_info_t *src)
  356. {
  357. presence_note_t *n, *nn;
  358. n = src->first_note;
  359. while (n) {
  360. nn = create_presence_note(&n->value, &n->lang);
  361. if (nn) add_tuple_note_no_wb(dst, nn);
  362. n = n->next;
  363. }
  364. }
  365. static inline void dup_tuple_extensions(presence_tuple_t *dst, presence_tuple_info_t *src)
  366. {
  367. extension_element_t *e, *ne;
  368. e = src->first_unknown_element;
  369. while (e) {
  370. ne = create_extension_element(&e->element);
  371. if (ne) add_tuple_extension_no_wb(dst, ne, 0);
  372. e = e->next;
  373. }
  374. /* add new extensions for tuple status */
  375. e = src->status.first_unknown_element;
  376. while (e) {
  377. ne = create_extension_element(&e->element);
  378. if (ne) add_tuple_extension_no_wb(dst, ne, 1);
  379. e = e->next;
  380. }
  381. }
  382. presence_tuple_t *presence_tuple_info2pa(presence_tuple_info_t *i, str *etag, time_t expires)
  383. {
  384. presence_tuple_t *t = NULL;
  385. int res;
  386. /* ID for the tuple is newly generated ! */
  387. res = new_presence_tuple(&i->contact, expires, &t, 1, NULL, &i->id, etag);
  388. if (res != 0) return NULL;
  389. t->data.priority = i->priority;
  390. t->data.status.basic = i->status.basic;
  391. /* add notes for tuple */
  392. dup_tuple_notes(t, i);
  393. /* add all extension elements */
  394. dup_tuple_extensions(t, i);
  395. return t;
  396. }
  397. void update_tuple(presentity_t *p, presence_tuple_t *t, presence_tuple_info_t *i, time_t expires)
  398. {
  399. t->expires = expires;
  400. t->data.priority = i->priority;
  401. t->data.status.basic = i->status.basic;
  402. str_free_content(&t->data.contact);
  403. str_dup(&t->data.contact, &i->contact);
  404. /* remove all old notes and extension elements for this tuple */
  405. free_tuple_notes(t);
  406. free_tuple_extensions(t);
  407. /* add new notes and new extension elemens for tuple */
  408. dup_tuple_notes(t, i);
  409. dup_tuple_extensions(t, i);
  410. if (use_db) db_update_presence_tuple(p, t, 1);
  411. }