int delete_phtable_query(str *pres_uri, int event, str* etag) { pres_entry_t* p; unsigned int hash_code; hash_code = core_hash(pres_uri, 0, phtable_size); lock_get(&pres_htable[hash_code].lock); p = search_phtable_etag(pres_uri, event, etag, hash_code); if(p == NULL) { LM_ERR("Record not found [%.*s]\n", etag->len, etag->s); lock_release(&pres_htable[hash_code].lock); return -1; } delete_phtable(p, hash_code); lock_release(&pres_htable[hash_code].lock); return 0; }
int update_presentity(struct sip_msg* msg, presentity_t* presentity, int* sent_reply) { // static db_ps_t my_ps_insert = NULL, my_ps_update_no_body = NULL, // my_ps_update_body = NULL; // static db_ps_t my_ps_delete = NULL, my_ps_query = NULL; db_key_t query_cols[13], update_keys[8], result_cols[1]; db_op_t query_ops[13]; db_val_t query_vals[13], update_vals[8]; int n_query_cols = 0; int n_update_cols = 0; str etag= {NULL, 0}; str notify_body = {NULL, 0}; str cur_etag= {NULL, 0}; str* rules_doc= NULL; str pres_uri= {NULL, 0}; pres_entry_t* p= NULL; unsigned int hash_code; unsigned int turn; str body = presentity->body; str *extra_hdrs = presentity->extra_hdrs; db_res_t *result= NULL; *sent_reply= 0; if(presentity->event->req_auth) { /* get rules_document */ if(presentity->event->get_rules_doc(&presentity->user, &presentity->domain, &rules_doc)) { LM_ERR("getting rules doc\n"); goto error; } } if(uandd_to_uri(presentity->user, presentity->domain, &pres_uri)< 0) { LM_ERR("constructing uri from user and domain\n"); goto error; } query_cols[n_query_cols] = &str_domain_col; query_ops[n_query_cols] = OP_EQ; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val = presentity->domain; n_query_cols++; query_cols[n_query_cols] = &str_username_col; query_ops[n_query_cols] = OP_EQ; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val = presentity->user; n_query_cols++; query_cols[n_query_cols] = &str_event_col; query_ops[n_query_cols] = OP_EQ; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val = presentity->event->name; n_query_cols++; query_cols[n_query_cols] = &str_etag_col; query_ops[n_query_cols] = OP_EQ; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val = presentity->etag; n_query_cols++; result_cols[0] = &str_etag_col; hash_code= core_hash(&pres_uri, NULL, phtable_size); if(presentity->etag_new) { if (msg && publ_send200ok(msg,presentity->expires,presentity->etag)<0) { LM_ERR("sending 200OK\n"); goto error; } *sent_reply= 1; /* insert new record in hash_table */ p = insert_phtable(&pres_uri, presentity->event->evp->parsed, &presentity->etag, presentity->sphere, 1); if (p==NULL) { LM_ERR("inserting record in hash table\n"); goto error; } /* insert new record into database */ query_cols[n_query_cols] = &str_expires_col; query_vals[n_query_cols].type = DB_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val = presentity->expires+ (int)time(NULL); n_query_cols++; query_cols[n_query_cols] = &str_sender_col; query_vals[n_query_cols].type = DB_STR; query_vals[n_query_cols].nul = 0; if( presentity->sender) { query_vals[n_query_cols].val.str_val = *presentity->sender; } else { query_vals[n_query_cols].val.str_val.s = ""; query_vals[n_query_cols].val.str_val.len = 0; } n_query_cols++; query_cols[n_query_cols] = &str_body_col; query_vals[n_query_cols].type = DB_BLOB; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val = body; n_query_cols++; query_cols[n_query_cols] = &str_received_time_col; query_vals[n_query_cols].type = DB_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val = presentity->received_time; n_query_cols++; if(extra_hdrs) { query_cols[n_query_cols] = &str_extra_hdrs_col; query_vals[n_query_cols].type = DB_BLOB; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val = *extra_hdrs; n_query_cols++; } if (pa_dbf.use_table(pa_db, &presentity_table) < 0) { LM_ERR("unsuccessful use_table\n"); goto error; } LM_DBG("inserting %d cols into table\n",n_query_cols); //CON_PS_REFERENCE(pa_db) = &my_ps_insert; if (pa_dbf.insert(pa_db, query_cols, query_vals, n_query_cols) < 0) { LM_ERR("inserting new record in database\n"); goto error; } goto send_notify; } else { lock_get(&pres_htable[hash_code].lock); p = search_phtable_etag(&pres_uri, presentity->event->evp->parsed, &presentity->etag, hash_code); if (p) { turn = p->last_turn++; LM_DBG("pres <%.*s> my turn is %d, current turn is %d\n",pres_uri.len, pres_uri.s, turn, p->current_turn); /* wait to get our turn as order of handling pubishs (need to wait the ongoing published to terminate before starting */ while (p && turn!=p->current_turn) { lock_release(&pres_htable[hash_code].lock); sleep_us(100); lock_get(&pres_htable[hash_code].lock); p = search_phtable_etag(&pres_uri, presentity->event->evp->parsed, &presentity->etag, hash_code); } } else { lock_release(&pres_htable[hash_code].lock); /* search also in db */ if (pa_dbf.use_table(pa_db, &presentity_table) < 0) { LM_ERR("unsuccessful sql use table\n"); goto error; } if (pa_dbf.query (pa_db, query_cols, query_ops, query_vals, result_cols, n_query_cols, 1, 0, &result) < 0) { LM_ERR("unsuccessful sql query\n"); goto error; } if(result== NULL) goto error; if (result->n <= 0) { pa_dbf.free_result(pa_db, result); LM_ERR("No E_Tag match [%.*s]\n", presentity->etag.len, presentity->etag.s); if (msg && sigb.reply(msg, 412, &pu_412_rpl, 0)==-1 ) { LM_ERR("sending '412 Conditional request failed' reply\n"); goto error; } *sent_reply= 1; goto done; } pa_dbf.free_result(pa_db, result); LM_INFO("*** found in db but not in htable [%.*s]\n", presentity->etag.len, presentity->etag.s); } /* record found */ if(presentity->expires == 0) { /* delete from hash table */ if(p && delete_phtable(p, hash_code)< 0) { LM_ERR("deleting record from hash table failed\n"); } /* presentity removed, pointer no longer valid */ p = NULL; lock_release(&pres_htable[hash_code].lock); if(msg && publ_send200ok(msg,presentity->expires,presentity->etag)<0) { LM_ERR("sending 200OK reply\n"); goto error; } *sent_reply= 1; if(publ_notify(presentity, pres_uri, body.s ? &body : 0, &presentity->etag, rules_doc, NULL, 1) < 0) { LM_ERR("while sending notify\n"); goto error; } if (pa_dbf.use_table(pa_db, &presentity_table) < 0) { LM_ERR("unsuccessful sql use table\n"); goto error; } //CON_PS_REFERENCE(pa_db) = &my_ps_delete; if(pa_dbf.delete(pa_db,query_cols,0,query_vals,n_query_cols)<0) { LM_ERR("unsuccessful sql delete operation"); goto error; } LM_DBG("Expires=0, deleted from db %.*s\n", presentity->user.len,presentity->user.s); /* Send another NOTIFY, this time rely on whatever is on the DB, * so in case there are no documents an empty * NOTIFY will be sent to the watchers */ if(publ_notify(presentity, pres_uri, NULL, NULL, rules_doc, NULL, 1) < 0) { LM_ERR("while sending notify\n"); goto error; } goto send_mxd_notify; } if(presentity->event->etag_not_new== 0) { if(generate_ETag(p?p->etag_count:0, &etag) < 0) { LM_ERR("while generating etag\n"); lock_release(&pres_htable[hash_code].lock); goto error; } cur_etag= etag; if(p) { update_pres_etag(p, &etag); lock_release(&pres_htable[hash_code].lock); } else { lock_release(&pres_htable[hash_code].lock); p = insert_phtable(&pres_uri, presentity->event->evp->parsed, &presentity->etag, presentity->sphere, 1); if ( p==NULL ) { LM_ERR("inserting record in hash table\n"); goto error; } } } else { lock_release(&pres_htable[hash_code].lock); cur_etag= presentity->etag; } n_update_cols= 0; update_keys[n_update_cols] = &str_etag_col; update_vals[n_update_cols].type = DB_STR; update_vals[n_update_cols].nul = 0; update_vals[n_update_cols].val.str_val = cur_etag; n_update_cols++; update_keys[n_update_cols] = &str_expires_col; update_vals[n_update_cols].type = DB_INT; update_vals[n_update_cols].nul = 0; update_vals[n_update_cols].val.int_val= presentity->expires + (int)time(NULL); n_update_cols++; update_keys[n_update_cols] = &str_received_time_col; update_vals[n_update_cols].type = DB_INT; update_vals[n_update_cols].nul = 0; update_vals[n_update_cols].val.int_val= presentity->received_time; n_update_cols++; update_keys[n_update_cols] = &str_sender_col; update_vals[n_update_cols].type = DB_STR; update_vals[n_update_cols].nul = 0; if( presentity->sender) { update_vals[n_update_cols].val.str_val = *presentity->sender; } else { update_vals[n_update_cols].val.str_val.s = ""; update_vals[n_update_cols].val.str_val.len = 0; } n_update_cols++; if(extra_hdrs) { update_keys[n_update_cols] = &str_extra_hdrs_col; update_vals[n_update_cols].type = DB_BLOB; update_vals[n_update_cols].nul = 0; update_vals[n_update_cols].val.str_val = *extra_hdrs; n_update_cols++; } if(body.s) { if (fix_remote_target) { if (dialog_fix_remote_target(&body, ¬ify_body)== 0) { body.s = notify_body.s; body.len = notify_body.len; } else { LM_ERR("Failed to fix remote target\n"); } } update_keys[n_update_cols] = &str_body_col; update_vals[n_update_cols].type = DB_BLOB; update_vals[n_update_cols].nul = 0; update_vals[n_update_cols].val.str_val = body; n_update_cols++; /* updated stored sphere */ if(sphere_enable && presentity->event->evp->parsed== EVENT_PRESENCE) { if(update_phtable(presentity, pres_uri, body)< 0) { LM_ERR("failed to update sphere for presentity\n"); goto error; } } //CON_PS_REFERENCE(pa_db) = &my_ps_update_body; } else { //CON_PS_REFERENCE(pa_db) = &my_ps_update_no_body; } if (pa_dbf.use_table(pa_db, &presentity_table) < 0) { LM_ERR("unsuccessful sql use table\n"); goto error; } if( pa_dbf.update( pa_db,query_cols, query_ops, query_vals, update_keys, update_vals, n_query_cols, n_update_cols )<0) { LM_ERR("updating published info in database\n"); goto error; } /* send 200OK */ if (msg && publ_send200ok(msg, presentity->expires, cur_etag)<0 ) { LM_ERR("sending 200OK reply\n"); goto error; } *sent_reply= 1; if(!body.s && !extra_hdrs) goto done; } send_notify: if (publ_notify(presentity, pres_uri, body.s?&body:0, NULL, rules_doc, NULL, 1)<0) { LM_ERR("while sending Notify requests to watchers\n"); goto error; } send_mxd_notify: /* if event dialog -> send Notify for presence also */ if(mix_dialog_presence && *pres_event_p && presentity->event->evp->parsed == EVENT_DIALOG) { str* dialog_body= NULL; LM_DBG("Publish for event dialog - try to send Notify for presence\n"); dialog_body = xml_dialog2presence(&pres_uri, &body); if(dialog_body) { /* send Notify for presence */ presentity->event = *pres_event_p; if (publ_notify(presentity, pres_uri, 0, NULL, 0, dialog_body, 1)<0) { LM_ERR("while sending Notify requests to watchers\n"); if(dialog_body && dialog_body!=FAKED_BODY) { xmlFree(dialog_body->s); pkg_free(dialog_body); } goto error; } if(dialog_body && dialog_body!=FAKED_BODY) { xmlFree(dialog_body->s); pkg_free(dialog_body); } } } done: /* allow next publish to be handled */ if (p) next_turn_phtable( p, hash_code); if (notify_body.s) xmlFree(notify_body.s); if(rules_doc) { if(rules_doc->s) pkg_free(rules_doc->s); pkg_free(rules_doc); } if(pres_uri.s) pkg_free(pres_uri.s); return 0; error: /* allow next publish to be handled */ if (p) next_turn_phtable( p, hash_code); if(result) pa_dbf.free_result(pa_db, result); if (notify_body.s) xmlFree(notify_body.s); if(rules_doc) { if(rules_doc->s) pkg_free(rules_doc->s); pkg_free(rules_doc); } if(pres_uri.s) pkg_free(pres_uri.s); return -1; }