Esempio n. 1
0
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;
}
Esempio n. 2
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, &notify_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;
}