123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- #include "presentity.h"
- #include <cds/dbid.h>
- #include "paerrno.h"
- #include "pa_mod.h"
- #include "tuple.h"
- #include "tuple_notes.h"
- #include "tuple_extensions.h"
- void add_presence_tuple_no_wb(presentity_t *_p, presence_tuple_t *_t);
- /*
- * Create a new presence_tuple
- */
- int new_presence_tuple(str* _contact, time_t expires,
- presence_tuple_t ** _t, int is_published, str *id,
- str *published_id, str *etag)
- {
- presence_tuple_t* tuple;
- int size = 0;
- int len;
- dbid_t tmp;
- if (!_t) {
- paerrno = PA_INTERNAL_ERROR;
- ERR("Invalid parameter value\n");
- return -1;
- }
- if (!id) {
- /* always needed (for PIDF documents, ...) */
- generate_dbid(tmp);
- len = dbid_strlen(tmp);
- }
- else len = id->len;
- size = sizeof(presence_tuple_t);
- if (etag) size += etag->len;
- if (published_id) size += published_id->len;
- if (!is_published) {
- if (_contact) size += _contact->len;
- /* Non-published tuples have contact allocated
- * together with other data! */
- }
- size += len;
- tuple = (presence_tuple_t*)mem_alloc(size);
- if (!tuple) {
- paerrno = PA_NO_MEMORY;
- ERR("No memory left: size=%d\n", size);
- return -1;
- }
- memset(tuple, 0, sizeof(presence_tuple_t));
- tuple->data.status.basic = presence_tuple_undefined_status;
-
- tuple->data.id.s = ((char*)tuple) + sizeof(presence_tuple_t);
- if (id) str_cpy(&tuple->data.id, id);
- else dbid_strcpy(&tuple->data.id, tmp, len);
-
- tuple->etag.s = after_str_ptr(&tuple->data.id);
- if (etag) str_cpy(&tuple->etag, etag);
- else tuple->etag.len = 0;
-
- tuple->published_id.s = after_str_ptr(&tuple->etag);
- if (published_id) str_cpy(&tuple->published_id, published_id);
- else tuple->published_id.len = 0;
-
- if (is_published) {
- str_dup(&tuple->data.contact, _contact);
- /* published contacts can change */
- }
- else {
- /* non-published contacts can NOT change !!! */
- tuple->data.contact.s = after_str_ptr(&tuple->published_id);
- if (_contact) str_cpy(&tuple->data.contact, _contact);
- else tuple->data.contact.len = 0;
- }
-
-
- tuple->expires = expires;
- tuple->data.priority = default_priority;
- tuple->is_published = is_published;
- *_t = tuple;
- return 0;
- }
- int db_read_tuples(presentity_t *_p, db_con_t* db)
- {
- db_key_t keys[] = { col_pres_id };
- db_op_t ops[] = { OP_EQ };
- db_val_t k_vals[] = { { DB_STR, 0, { .str_val = _p->pres_id } } };
- int i;
- int r = 0;
- db_res_t *res = NULL;
- db_key_t result_cols[] = { col_basic, col_expires, col_priority,
- col_contact, col_tupleid, col_etag,
- col_published_id
- } ;
-
- if (!use_db) return 0;
- if (pa_dbf.use_table(db, presentity_contact_table) < 0) {
- ERR("Error in use_table\n");
- return -1;
- }
-
- if (pa_dbf.query (db, keys, ops, k_vals,
- result_cols, 1, sizeof(result_cols) / sizeof(db_key_t),
- 0, &res) < 0) {
- ERR("Error while querying DB\n");
- return -1;
- }
- if (!res) return 0; /* ? */
-
- for (i = 0; i < res->n; i++) {
- presence_tuple_t *tuple = NULL;
- db_row_t *row = &res->rows[i];
- db_val_t *row_vals = ROW_VALUES(row);
- str contact = STR_NULL;
- basic_tuple_status_t basic = presence_tuple_undefined_status;
- str id = STR_NULL;
- str etag = STR_NULL;
- str published_id = STR_NULL;
-
- time_t expires = 0;
- double priority = row_vals[2].val.double_val;
-
- #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)
- #define get_int_val(i,dst) do{if(!row_vals[i].nul){dst=row_vals[i].val.int_val;}}while(0)
- #define get_time_val(i,dst) do{if(!row_vals[i].nul){dst=row_vals[i].val.time_val;}}while(0)
- get_int_val(0, basic);
- get_time_val(1, expires);
- get_str_val(3, contact);
- get_str_val(4, id);
- get_str_val(5, etag);
- get_str_val(6, published_id);
-
- #undef get_str_val
- #undef get_time_val
- r = new_presence_tuple(&contact, expires, &tuple, 1, &id,
- &published_id, &etag) | r;
- if (tuple) {
- tuple->data.status.basic = basic;
- LOG(L_DBG, "read tuple %.*s\n", id.len, id.s);
- tuple->data.priority = priority;
- db_read_tuple_notes(_p, tuple, db);
- db_read_tuple_extensions(_p, tuple, db);
-
- add_presence_tuple_no_wb(_p, tuple);
- }
- }
-
- pa_dbf.free_result(db, res);
- return r;
- }
- static int set_tuple_db_data(presentity_t *_p, presence_tuple_t *tuple,
- db_key_t *cols, db_val_t *vals, int *col_cnt)
- {
- int n_updates = 0;
- cols[n_updates] = col_tupleid;
- vals[n_updates].type = DB_STR;
- vals[n_updates].nul = 0;
- vals[n_updates].val.str_val = tuple->data.id;
- n_updates++;
-
- cols[n_updates] = col_pres_id;
- vals[n_updates].type = DB_STR;
- vals[n_updates].nul = 0;
- vals[n_updates].val.str_val = _p->pres_id;
- n_updates++;
-
- cols[n_updates] = col_basic;
- vals[n_updates].type = DB_INT;
- vals[n_updates].nul = 0;
- vals[n_updates].val.int_val = tuple->data.status.basic;
- n_updates++;
- cols[n_updates] = col_contact;
- vals[n_updates].type = DB_STR;
- vals[n_updates].nul = 0;
- vals[n_updates].val.str_val = tuple->data.contact;
- n_updates++;
-
- cols[n_updates] = col_etag;
- vals[n_updates].type = DB_STR;
- vals[n_updates].nul = 0;
- vals[n_updates].val.str_val = tuple->etag;
- n_updates++;
- cols[n_updates] = col_published_id;
- vals[n_updates].type = DB_STR;
- vals[n_updates].nul = 0;
- vals[n_updates].val.str_val = tuple->published_id;
- n_updates++;
- if (tuple->data.priority != 0.0) {
- cols[n_updates] = col_priority;
- vals[n_updates].type = DB_DOUBLE;
- vals[n_updates].nul = 0;
- vals[n_updates].val.double_val = tuple->data.priority;
- n_updates++;
- }
- if (tuple->expires != 0) {
- cols[n_updates] = col_expires;
- vals[n_updates].type = DB_DATETIME;
- vals[n_updates].nul = 0;
- vals[n_updates].val.time_val = tuple->expires;
- n_updates++;
- }
- *col_cnt = n_updates;
- return 0;
- }
- static int db_add_presence_tuple(presentity_t *_p, presence_tuple_t *t)
- {
- db_key_t query_cols[20];
- db_val_t query_vals[20];
- int n_query_cols = 0;
- int res;
- if (!use_db) return 0;
- if (!t->is_published) return 0; /* store only published tuples */
-
- if (set_tuple_db_data(_p, t, query_cols,
- query_vals, &n_query_cols) != 0) {
- return -1;
- }
-
- if (pa_dbf.use_table(pa_db, presentity_contact_table) < 0) {
- LOG(L_ERR, "db_add_presence_tuple: Error in use_table\n");
- return -1;
- }
- if (pa_dbf.insert(pa_db, query_cols, query_vals, n_query_cols) < 0) {
- LOG(L_ERR, "db_add_presence_tuple: Can't insert record\n");
- return -1;
- }
-
- res = 0;
- if (db_add_tuple_notes(_p, t) < 0) {
- res = -2;
- ERR("can't add tuple notes into DB\n");
- }
- if (db_add_tuple_extensions(_p, t) < 0) {
- res = -3;
- ERR("can't add tuple extensions into DB\n");
- }
- return res;
- }
- static int db_remove_presence_tuple(presentity_t *_p, presence_tuple_t *t)
- {
- db_key_t keys[] = { col_pres_id, col_tupleid };
- db_op_t ops[] = { OP_EQ, OP_EQ };
- db_val_t k_vals[] = { { DB_STR, 0, { .str_val = _p->pres_id } },
- { DB_STR, 0, { .str_val = t->data.id } } };
-
- if (!use_db) return 0;
- if (!t->is_published) return 0; /* store only published tuples */
- db_remove_tuple_notes(_p, t);
- db_remove_tuple_extensions(_p, t);
-
- if (pa_dbf.use_table(pa_db, presentity_contact_table) < 0) {
- LOG(L_ERR, "db_remove_presence_tuple: Error in use_table\n");
- return -1;
- }
- if (pa_dbf.delete(pa_db, keys, ops, k_vals, 2) < 0) {
- LOG(L_ERR, "db_remove_presence_tuple: Can't delete record\n");
- return -1;
- }
-
- return 0;
- }
- int db_update_presence_tuple(presentity_t *_p, presence_tuple_t *t, int update_notes_and_ext)
- {
- db_key_t keys[] = { col_pres_id, col_tupleid };
- db_op_t ops[] = { OP_EQ, OP_EQ };
- db_val_t k_vals[] = { { DB_STR, 0, { .str_val = _p->pres_id } },
- { DB_STR, 0, { .str_val = t->data.id } } };
-
- db_key_t query_cols[20];
- db_val_t query_vals[20];
- int n_query_cols = 0;
- if (!use_db) return 0;
- if (!t->is_published) return 0; /* store only published tuples */
- if (set_tuple_db_data(_p, t, query_cols,
- query_vals, &n_query_cols) != 0) {
- return -1;
- }
-
- if (pa_dbf.use_table(pa_db, presentity_contact_table) < 0) {
- ERR("Error in use_table\n");
- return -1;
- }
- if (pa_dbf.update(pa_db, keys, ops, k_vals,
- query_cols, query_vals, 2, n_query_cols) < 0) {
- ERR("Can't update record\n");
- return -1;
- }
- if (update_notes_and_ext) {
- db_update_tuple_notes(_p, t);
- db_update_tuple_extensions(_p, t);
- }
-
- return 0;
- }
- void add_presence_tuple_no_wb(presentity_t *_p, presence_tuple_t *_t)
- {
- DOUBLE_LINKED_LIST_ADD(_p->data.first_tuple,
- _p->data.last_tuple, (presence_tuple_info_t*)_t);
- }
- void add_presence_tuple(presentity_t *_p, presence_tuple_t *_t)
- {
- add_presence_tuple_no_wb(_p, _t);
- if (use_db) db_add_presence_tuple(_p, _t);
- }
- void remove_presence_tuple(presentity_t *_p, presence_tuple_t *_t)
- {
- DOUBLE_LINKED_LIST_REMOVE(_p->data.first_tuple,
- _p->data.last_tuple, (presence_tuple_info_t*)_t);
- if (use_db) db_remove_presence_tuple(_p, _t);
- }
- /*
- * Free all memory associated with a presence_tuple
- */
- void free_presence_tuple(presence_tuple_t * _t)
- {
- if (_t) {
- free_tuple_notes(_t);
- free_tuple_extensions(_t);
- if (_t->is_published) {
- /* Warning: not-published tuples have contact allocated
- * together with other data => contact can't change! */
- str_free_content(&_t->data.contact);
- }
- mem_free(_t);
- }
- }
- /*
- * Find a presence_tuple for contact _contact on presentity _p
- */
- int find_registered_presence_tuple(str* _contact, presentity_t *_p, presence_tuple_t ** _t)
- {
- presence_tuple_t *tuple;
- if (!_contact || !_contact->len || !_p || !_t) {
- paerrno = PA_INTERNAL_ERROR;
- LOG(L_ERR, "find_presence_tuple(): Invalid parameter value\n");
- return -1;
- }
- tuple = get_first_tuple(_p);
- while (tuple) {
- /* only contacts from usrloc should have unique contact - published
- * may be more times !!! */
- if (!tuple->is_published) {
- if (str_nocase_equals(&tuple->data.contact, _contact) == 0) {
- *_t = tuple;
- return 0;
- }
- }
- tuple = (presence_tuple_t*)tuple->data.next;
- }
- return 1;
- }
- /*
- * Find a presence_tuple on presentity _p
- */
- int find_presence_tuple_id(str* id, presentity_t *_p, presence_tuple_t ** _t)
- {
- presence_tuple_t *tuple;
- if (!id || !id->len || !_p || !_t) {
- paerrno = PA_INTERNAL_ERROR;
- LOG(L_ERR, "find_presence_tuple_id(): Invalid parameter value\n");
- return -1;
- }
- tuple = get_first_tuple(_p);
- while (tuple) {
- if (str_case_equals(&tuple->data.id, id) == 0) {
- *_t = tuple;
- return 0;
- }
- tuple = (presence_tuple_t*)tuple->data.next;
- }
- return 1;
- }
- presence_tuple_t *find_published_tuple(presentity_t *presentity, str *etag, str *id)
- {
- presence_tuple_t *tuple = get_first_tuple(presentity);
- while (tuple) {
- if (str_case_equals(&tuple->etag, etag) == 0) {
- if (str_case_equals(&tuple->published_id, id) == 0)
- return tuple;
- }
- tuple = get_next_tuple(tuple);
- }
- return NULL;
- }
- static inline void dup_tuple_notes(presence_tuple_t *dst, presence_tuple_info_t *src)
- {
- presence_note_t *n, *nn;
- n = src->first_note;
- while (n) {
- nn = create_presence_note(&n->value, &n->lang);
- if (nn) add_tuple_note_no_wb(dst, nn);
- n = n->next;
- }
- }
-
- static inline void dup_tuple_extensions(presence_tuple_t *dst, presence_tuple_info_t *src)
- {
- extension_element_t *e, *ne;
- e = src->first_unknown_element;
- while (e) {
- ne = create_extension_element(&e->element);
- if (ne) add_tuple_extension_no_wb(dst, ne, 0);
-
- e = e->next;
- }
-
- /* add new extensions for tuple status */
- e = src->status.first_unknown_element;
- while (e) {
- ne = create_extension_element(&e->element);
- if (ne) add_tuple_extension_no_wb(dst, ne, 1);
-
- e = e->next;
- }
- }
- presence_tuple_t *presence_tuple_info2pa(presence_tuple_info_t *i, str *etag, time_t expires)
- {
- presence_tuple_t *t = NULL;
- int res;
-
- /* ID for the tuple is newly generated ! */
- res = new_presence_tuple(&i->contact, expires, &t, 1, NULL, &i->id, etag);
- if (res != 0) return NULL;
- t->data.priority = i->priority;
- t->data.status.basic = i->status.basic;
- /* add notes for tuple */
- dup_tuple_notes(t, i);
- /* add all extension elements */
- dup_tuple_extensions(t, i);
- return t;
- }
- void update_tuple(presentity_t *p, presence_tuple_t *t, presence_tuple_info_t *i, time_t expires)
- {
- t->expires = expires;
- t->data.priority = i->priority;
- t->data.status.basic = i->status.basic;
-
- str_free_content(&t->data.contact);
- str_dup(&t->data.contact, &i->contact);
- /* remove all old notes and extension elements for this tuple */
- free_tuple_notes(t);
- free_tuple_extensions(t);
-
- /* add new notes and new extension elemens for tuple */
- dup_tuple_notes(t, i);
- dup_tuple_extensions(t, i);
- if (use_db) db_update_presence_tuple(p, t, 1);
- }
|