modules/rls/rls_db.c
7665c794
 /*
  * rls db - RLS database support 
  *
  * Copyright (C) 2011 Crocodile RCS Ltd
  *
  * This file is part of Kamailio, a free SIP server.
  *
  * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
7665c794
  */
 
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "../../mem/mem.h"
 #include "../../mem/shm_mem.h"
 #include "../../dprint.h"
 #include "../../lib/srdb1/db.h"
 #include "../../parser/msg_parser.h"
 #include "../../parser/parse_from.h"
6d33ee03
 #include "../../hashes.h"
7665c794
 
 #include "rls.h"
 
 #define CONT_COPYDB(buf, dest, source)\
 	do{ \
 	dest.s= (char*)buf+ size;\
 	memcpy(dest.s, source, strlen(source));\
 	dest.len= strlen(source);\
 	size+= strlen(source); \
 	} while(0);
 
 /* database connection */
f968ac71
 extern db1_con_t *rls_db;
 extern db_func_t rls_dbf;
7665c794
 
 extern void update_a_sub(subs_t *subs_copy );
 
 /******************************************************************************/
 
 shtable_t rls_new_shtable(int hash_size)
 {
   LM_ERR( "rls_new_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
   return(NULL);
 }
 
 /******************************************************************************/
 
 void rls_destroy_shtable(shtable_t htable, int hash_size)
 {
   LM_ERR( "rls_destroy_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
 }
 
 /******************************************************************************/
 
 int rls_insert_shtable(shtable_t htable,unsigned int hash_code, subs_t* subs)
 {
   LM_ERR( "rls_insert_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
   return(-1);
 }
 
 /******************************************************************************/
 
 subs_t* rls_search_shtable(shtable_t htable,str callid,str to_tag,
 		str from_tag,unsigned int hash_code)
 {
   LM_ERR( "rls_search_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
   return(NULL);
 }
 
 /******************************************************************************/
 
039c0c9f
 int rls_delete_shtable(shtable_t htable,unsigned int hash_code, subs_t* subs)
7665c794
 {
   LM_ERR( "rls_delete_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
   return(-1);
 }
 
 /******************************************************************************/
 
 int rls_update_shtable(shtable_t htable,unsigned int hash_code, 
 		subs_t* subs, int type)
 {
   LM_ERR( "rls_update_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
   return(-1);
 }
 
 /******************************************************************************/
 
5cb9b9bd
 void rls_update_db_subs_timer(db1_con_t *db,db_func_t dbf, shtable_t hash_table,
7665c794
 	int htable_size, int no_lock, handle_expired_func_t handle_expired_func)
 {
5cb9b9bd
   LM_ERR( "rls_update_db_subs_timer shouldn't be called in RLS_DB_ONLY mode\n" );
7665c794
 }
 
 /******************************************************************************/
 /******************************************************************************/
 
 int delete_expired_subs_rlsdb( void )
 
 {
6d33ee03
 	db_key_t query_cols[3], result_cols[3], update_cols[1];
 	db_val_t query_vals[3], update_vals[1], *values;
af8230b1
 	db_op_t query_ops[2];
6d33ee03
 	db_row_t *rows;
 	db1_res_t *result = NULL;
1a91ac34
 	int n_query_cols = 0, n_result_cols = 0;
6d33ee03
 	int r_callid_col = 0, r_to_tag_col = 0, r_from_tag_col = 0;
7b64e538
 	int i, nr_rows;
6d33ee03
 	subs_t subs;
 	str rlsubs_did = {0, 0};
10327c61
 	db_query_f query_fn = rls_dbf.query_lock ? rls_dbf.query_lock : rls_dbf.query;
7665c794
 
f968ac71
 	if(rls_db == NULL)
7665c794
 	{
 		LM_ERR("null database connection\n");
6d33ee03
 		goto error;
7665c794
 	}
 
f968ac71
 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
7665c794
 	{
 		LM_ERR("use table failed\n");
6d33ee03
 		goto error;
7665c794
 	}
 
6d33ee03
 	query_cols[n_query_cols]= &str_expires_col;
 	query_vals[n_query_cols].type = DB1_INT;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.int_val= (int)time(NULL) - rls_expires_offset;
 	query_ops[n_query_cols]= OP_LT;
 	n_query_cols++;
 
af8230b1
 	query_cols[n_query_cols]= &str_updated_col;
 	query_vals[n_query_cols].type = DB1_INT;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.int_val= NO_UPDATE_TYPE;
 	query_ops[n_query_cols]= OP_EQ;
 	n_query_cols++;
 
6d33ee03
 	result_cols[r_callid_col=n_result_cols++] = &str_callid_col;
 	result_cols[r_to_tag_col=n_result_cols++] = &str_to_tag_col;
 	result_cols[r_from_tag_col=n_result_cols++] = &str_from_tag_col;
 
10327c61
 	if (rls_dbf.start_transaction)
 	{
 		if (rls_dbf.start_transaction(rls_db, DB_LOCKING_WRITE) < 0)
 		{
 			LM_ERR("in start_transaction\n");
 			goto error;
 		}
 	}
 
 	if(query_fn(rls_db, query_cols, query_ops, query_vals, result_cols, 
6d33ee03
 				n_query_cols, n_result_cols, 0, &result )< 0)
7665c794
 	{
6d33ee03
 		LM_ERR("Can't query db\n");
 		goto error;
7665c794
 	}
 
6d33ee03
 	if(result == NULL) goto error;
 
7b64e538
 	rows = RES_ROWS(result);
 	nr_rows = RES_ROW_N(result);
 
 	for (i = 0; i < nr_rows; i++)
6d33ee03
 	{
7b64e538
 		memset(&subs, 0, sizeof(subs_t));
 		values = ROW_VALUES(&rows[i]);
6d33ee03
 
 		subs.callid.s = (char *) VAL_STRING(&values[r_callid_col]);
 		subs.callid.len = strlen(subs.callid.s);
 		subs.to_tag.s = (char *) VAL_STRING(&values[r_to_tag_col]);
 		subs.to_tag.len = strlen(subs.to_tag.s);
 		subs.from_tag.s = (char *) VAL_STRING(&values[r_from_tag_col]);
 		subs.from_tag.len = strlen(subs.from_tag.s);
 
 		if (CONSTR_RLSUBS_DID(&subs, &rlsubs_did) < 0)
 		{
 			LM_ERR("cannot build rls subs did\n");
 			goto error;
 		}
5235a1d6
 		subs.updated = core_hash(&rlsubs_did, NULL, 0) %
 			(waitn_time * rls_notifier_poll_rate * rls_notifier_processes);
6d33ee03
 
 		n_query_cols = 0;
 
 		query_cols[n_query_cols] = &str_callid_col;
 		query_vals[n_query_cols].type = DB1_STR;
 		query_vals[n_query_cols].nul = 0;
 		query_vals[n_query_cols].val.str_val = subs.callid;
 		n_query_cols++;
 
 		query_cols[n_query_cols] = &str_to_tag_col;
 		query_vals[n_query_cols].type = DB1_STR;
 		query_vals[n_query_cols].nul = 0;
 		query_vals[n_query_cols].val.str_val = subs.to_tag;
 		n_query_cols++;
 
 		query_cols[n_query_cols] = &str_from_tag_col;
 		query_vals[n_query_cols].type = DB1_STR;
 		query_vals[n_query_cols].nul = 0;
 		query_vals[n_query_cols].val.str_val = subs.from_tag;
 		n_query_cols++;
 
1a91ac34
 		update_cols[0] = &str_updated_col;
 		update_vals[0].type = DB1_INT;
 		update_vals[0].nul = 0;
 		update_vals[0].val.int_val = subs.updated;
6d33ee03
 
 		if(rls_dbf.update(rls_db, query_cols, 0, query_vals,
1a91ac34
 			update_cols,update_vals,n_query_cols, 1) < 0)
6d33ee03
 		{
 			LM_ERR("db update failed for expired subs\n");
 			goto error;
 		}
 
 		pkg_free(rlsubs_did.s);
 	}
 
b5e1edb8
 	rls_dbf.free_result(rls_db, result);
10327c61
 
 	if (rls_dbf.end_transaction)
 	{
 		if (rls_dbf.end_transaction(rls_db) < 0)
 		{
 			LM_ERR("in end_transaction\n");
 			goto error;
 		}
 	}
 
6d33ee03
 	return 1;
 
 error:
 	if (result) rls_dbf.free_result(rls_db, result);
 	if (rlsubs_did.s) pkg_free(rlsubs_did.s);
10327c61
 
 	if (rls_dbf.abort_transaction)
 	{
 		if (rls_dbf.abort_transaction(rls_db) < 0)
 			LM_ERR("in abort_transaction\n");
 	}
 
6d33ee03
 	return -1;
7665c794
 }
 
 /******************************************************************************/
 
 int delete_rlsdb( str *callid, str *to_tag, str *from_tag ) 
 
 {
  	int rval;
 	db_key_t query_cols[3];
 	db_val_t query_vals[3];
 	int n_query_cols = 0;
 
f968ac71
 	if(rls_db == NULL)
7665c794
 	{
 		LM_ERR("null database connection\n");
 		return(-1);
 	}
 
f968ac71
 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
7665c794
 	{
 		LM_ERR("use table failed\n");
 		return(-1);
 	}
 	
6d7e23db
 	query_cols[n_query_cols] = &str_callid_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= *callid;
 	n_query_cols++;
7665c794
 
6d7e23db
 	query_cols[n_query_cols] = &str_to_tag_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= *to_tag;
 	n_query_cols++;
7665c794
 
 	if (from_tag)
 	{
6d7e23db
 		query_cols[n_query_cols] = &str_from_tag_col;
 		query_vals[n_query_cols].type = DB1_STR;
 		query_vals[n_query_cols].nul = 0;
 		query_vals[n_query_cols].val.str_val= *from_tag;
7665c794
 		n_query_cols++;
 	}
 
f968ac71
 	rval = rls_dbf.delete(rls_db, query_cols, 0, query_vals, n_query_cols);
7665c794
 
 	if (rval < 0)
 	{
 		LM_ERR("Can't delete in db\n");
 		return(-1);
 	}
 
 	return(1);
 }
 
 /******************************************************************************/
 
6d7e23db
 int update_dialog_notify_rlsdb(subs_t *subs)
7665c794
 
 {
 	db_key_t query_cols[3];
 	db_val_t query_vals[3];
6d7e23db
 	db_key_t data_cols[3];
 	db_val_t data_vals[3];
7665c794
 	int n_query_cols = 0, n_data_cols=0;
 
 	if (subs==NULL) return(-1);
 
f968ac71
 	if(rls_db == NULL)
7665c794
 	{
 		LM_ERR("null database connection\n");
 		return(-1);
 	}
 
f968ac71
 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
7665c794
 	{
 		LM_ERR("use table failed\n");
 		return(-1);
 	}
6d7e23db
 
 	subs->local_cseq++;
 	subs->version++;
7665c794
 	
6d7e23db
 	query_cols[n_query_cols] = &str_callid_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= subs->callid;
7665c794
 	n_query_cols++;
 
6d7e23db
 	query_cols[n_query_cols] = &str_to_tag_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= subs->to_tag;
7665c794
 	n_query_cols++;
 
6d7e23db
 	query_cols[n_query_cols] = &str_from_tag_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= subs->from_tag;
7665c794
 	n_query_cols++;
 
6d7e23db
 	data_cols[n_data_cols]=&str_local_cseq_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val= subs->local_cseq;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols]=&str_version_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val= subs->version;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] =&str_status_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val= subs->status;
7665c794
 	n_data_cols++;
 
f968ac71
 	if(rls_dbf.update(rls_db, query_cols, 0, query_vals,
7665c794
                     data_cols,data_vals,n_query_cols,n_data_cols) < 0)
 	{
 		LM_ERR("Failed update db\n");
 		return(-1);
 	}
 
 	return(0);
 }
 
 /******************************************************************************/
 
b90adb0d
 int update_all_subs_rlsdb(str *watcher_user, str *watcher_domain, str *evt)
7665c794
 {
 	db_key_t query_cols[3];
 	db_val_t query_vals[3];
6d7e23db
 	db_key_t result_cols[20];
7665c794
 	int n_query_cols = 0, n_result_cols=0;
6d7e23db
 	int r_pres_uri_col, r_callid_col, r_to_tag_col, r_from_tag_col;
 	int r_event_col, r_expires_col;
7665c794
 	db1_res_t *result= NULL;
  	db_val_t *values;
 	db_row_t *rows;
 	int nr_rows, size, loop;
 	subs_t *dest;
 	event_t parsed_event;
 
f968ac71
 	if(rls_db == NULL)
7665c794
 	{
 		LM_ERR("null database connection\n");
 		return(-1);
 	}
 
f968ac71
 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
7665c794
 	{
 		LM_ERR("use table failed\n");
 		return(-1);
 	}
 	
6d7e23db
 	query_cols[n_query_cols] = &str_watcher_username_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
b90adb0d
 	query_vals[n_query_cols].val.str_val= *watcher_user;
7665c794
 	n_query_cols++;
 
6d7e23db
 	query_cols[n_query_cols] = &str_watcher_domain_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
b90adb0d
 	query_vals[n_query_cols].val.str_val= *watcher_domain;
7665c794
 	n_query_cols++;
 
6d7e23db
 	query_cols[n_query_cols] = &str_event_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= *evt;
7665c794
 	n_query_cols++;
 
 	result_cols[r_pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
 	result_cols[r_callid_col=n_result_cols++] = &str_callid_col;
 	result_cols[r_to_tag_col=n_result_cols++] = &str_to_tag_col;
 	result_cols[r_from_tag_col=n_result_cols++] = &str_from_tag_col;
 	result_cols[r_event_col=n_result_cols++] = &str_event_col;
 	result_cols[r_expires_col=n_result_cols++] = &str_expires_col;
 
f968ac71
 	if(rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols, 
7665c794
 				n_query_cols, n_result_cols, 0, &result )< 0)
 	{
 		LM_ERR("Can't query db\n");
f968ac71
 		if(result) rls_dbf.free_result(rls_db, result);
7665c794
 		return(-1);
 	}
 
 	if(result == NULL) return(-1);
 
 	nr_rows = RES_ROW_N(result);
 
7b64e538
 	rows = RES_ROWS(result);
7665c794
 	/* get the results and fill in return data structure */
 	for (loop=0; loop <nr_rows; loop++)
 	{
7b64e538
 		values = ROW_VALUES(&rows[loop]);
7665c794
 
 		size= sizeof(subs_t) +
 			( strlen(VAL_STRING(values+r_pres_uri_col))
 			+ strlen(VAL_STRING(values+r_to_tag_col))
 			+ strlen(VAL_STRING(values+r_from_tag_col))
6d7e23db
 			+ strlen(VAL_STRING(values+r_callid_col)))*sizeof(char);
7665c794
 
 		dest= (subs_t*)pkg_malloc(size);
 	
 		if(dest== NULL)
 		{
 			LM_ERR( "Can't allocate memory\n" );
f968ac71
 			rls_dbf.free_result(rls_db, result);
7665c794
 			return(-1);
 		}
 		memset(dest, 0, size);
 		size= sizeof(subs_t);
 
 		CONT_COPYDB(dest, dest->pres_uri, VAL_STRING(values+r_pres_uri_col))
 		CONT_COPYDB(dest, dest->to_tag, VAL_STRING(values+r_to_tag_col))
 		CONT_COPYDB(dest, dest->from_tag, VAL_STRING(values+r_from_tag_col))
 		CONT_COPYDB(dest, dest->callid, VAL_STRING(values+r_callid_col))
 
6d7e23db
 		dest->event = pres_contains_event(evt, &parsed_event);
7665c794
 		if(dest->event == NULL)
 		{
 			LM_ERR("event not found and set to NULL\n");
 		}
 
 		dest->expires= VAL_INT(values+r_expires_col);
b90adb0d
 		dest->watcher_user.s= watcher_user->s;
 		dest->watcher_user.len= watcher_user->len;
 		dest->watcher_domain.s= watcher_domain->s;
 		dest->watcher_domain.len= watcher_domain->len;
7665c794
 
 		update_a_sub(dest);
 	}
 
f968ac71
 	rls_dbf.free_result(rls_db, result);
7665c794
 	return(1);	
 }
 
 /******************************************************************************/
 
6d7e23db
 int update_dialog_subscribe_rlsdb(subs_t *subs)
7665c794
 
 {
 	db_key_t query_cols[3];
 	db_val_t query_vals[3];
dff68160
 	db_key_t data_cols[3];
 	db_val_t data_vals[3];
6d7e23db
 	int n_query_cols = 0, n_data_cols=0;
7665c794
 
 	if (subs==NULL) return(-1);
 
f968ac71
 	if(rls_db == NULL)
7665c794
 	{
 		LM_ERR("null database connection\n");
 		return(-1);
 	}
 
f968ac71
 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
7665c794
 	{
 		LM_ERR("use table failed\n");
 		return(-1);
 	}
 	
6d7e23db
 	query_cols[n_query_cols] = &str_callid_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= subs->callid;
7665c794
 	n_query_cols++;
 
6d7e23db
 	query_cols[n_query_cols] = &str_to_tag_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= subs->to_tag;
7665c794
 	n_query_cols++;
 
6d7e23db
 	query_cols[n_query_cols] = &str_from_tag_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= subs->from_tag;
7665c794
 	n_query_cols++;
 
6d7e23db
 	data_cols[n_data_cols] = &str_expires_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val = subs->expires + (int)time(NULL);
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] = &str_remote_cseq_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val= subs->remote_cseq;
7665c794
 	n_data_cols++;
 
dff68160
 	data_cols[n_data_cols] = &str_updated_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val= subs->updated;
 	n_data_cols++;
 
f968ac71
 	if(rls_dbf.update(rls_db, query_cols, 0, query_vals,
7665c794
                     data_cols,data_vals,n_query_cols,n_data_cols) < 0)
 	{
 		LM_ERR("Failed update db\n");
 		return(-1);
 	}
 	
 	return(0);
 }
 
 /******************************************************************************/
 
 int insert_rlsdb( subs_t *s )
 
 {
b90adb0d
 	db_key_t data_cols[23];
 	db_val_t data_vals[23];
7665c794
 	int n_data_cols = 0;
 
 	if (s==NULL) return(-1);
 
f968ac71
 	if(rls_db == NULL)
7665c794
 	{
 		LM_ERR("null database connection\n");
 		return(-1);
 	}
 
f968ac71
 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
7665c794
 	{
 		LM_ERR("use table failed\n");
 		return(-1);
 	}
 	
6d7e23db
 	data_cols[n_data_cols] = &str_presentity_uri_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val= s->pres_uri;
7665c794
 	n_data_cols++;
 	
6d7e23db
 	data_cols[n_data_cols] = &str_callid_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val= s->callid;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] = &str_to_tag_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val= s->to_tag;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] = &str_from_tag_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val= s->from_tag;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] = &str_to_user_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->to_user;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] = &str_to_domain_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->to_domain;
7665c794
 	n_data_cols++;
b90adb0d
 
 	data_cols[n_data_cols] = &str_from_user_col;
6d7e23db
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->from_user;
7665c794
 	n_data_cols++;
 
b90adb0d
 	data_cols[n_data_cols] = &str_from_domain_col;
6d7e23db
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->from_domain;
7665c794
 	n_data_cols++;
 
b90adb0d
 	data_cols[n_data_cols] = &str_watcher_username_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->watcher_user;
 	n_data_cols++;
 
 	data_cols[n_data_cols] = &str_watcher_domain_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->watcher_domain;
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] = &str_event_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->event->name;
7665c794
 	n_data_cols++;	
 
6d7e23db
 	data_cols[n_data_cols] = &str_event_id_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->event_id;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols]=&str_local_cseq_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val= s->local_cseq;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols]=&str_remote_cseq_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val= s->remote_cseq;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] =&str_expires_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val = s->expires + (int)time(NULL);
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] =&str_status_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val= s->status;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] =&str_reason_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val= s->reason;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] =&str_record_route_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->record_route;
7665c794
 	n_data_cols++;
 	
6d7e23db
 	data_cols[n_data_cols] =&str_contact_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->contact;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] =&str_local_contact_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val = s->local_contact;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols] =&str_socket_info_col;
 	data_vals[n_data_cols].type = DB1_STR;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.str_val= s->sockinfo_str;
7665c794
 	n_data_cols++;
 
6d7e23db
 	data_cols[n_data_cols]=&str_version_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val= s->version;
7665c794
 	n_data_cols++;
dff68160
 
 	data_cols[n_data_cols]=&str_updated_col;
 	data_vals[n_data_cols].type = DB1_INT;
 	data_vals[n_data_cols].nul = 0;
 	data_vals[n_data_cols].val.int_val= s->updated;
 	n_data_cols++;
7665c794
 	
f968ac71
 	if(rls_dbf.insert(rls_db, data_cols, data_vals, n_data_cols) < 0)
7665c794
 	{
 		LM_ERR("db insert failed\n");
 		return(-1);
 	}
 
 	return(0);
 }
 
 /******************************************************************************/
 
6d7e23db
 int get_dialog_subscribe_rlsdb(subs_t *subs) 
7665c794
 
 {
  	db1_res_t *result= NULL;
 	db_key_t query_cols[3];
6d7e23db
 	db_val_t query_vals[3], *values;
 	db_key_t result_cols[5];
 	db_row_t *rows;
 	int n_query_cols = 0, n_result_cols = 0;
f2fee212
 	int pres_uri_col, rcseq_col, lcseq_col, version_col, rroute_col;
6d7e23db
 	int nr_rows;
 	int r_remote_cseq, r_local_cseq, r_version;
 	char *r_pres_uri, *r_record_route;
10327c61
 	db_query_f query_fn = rls_dbf.query_lock ? rls_dbf.query_lock : rls_dbf.query;
 	
f968ac71
 	if(rls_db == NULL)
7665c794
 	{
 		LM_ERR("null database connection\n");
 		return(-1);
 	}
 
6d7e23db
 	if (subs == NULL)
 	{
 		LM_ERR("null subscriptions\n");
 		return(-1);
 	}
 
f968ac71
 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
7665c794
 	{
 		LM_ERR("use table failed\n");
 		return(-1);
 	}
 	
6d7e23db
 	query_cols[n_query_cols] = &str_callid_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= subs->callid;
7665c794
 	n_query_cols++;
 
6d7e23db
 	query_cols[n_query_cols] = &str_to_tag_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= subs->to_tag;
7665c794
 	n_query_cols++;
 
6d7e23db
 	query_cols[n_query_cols] = &str_from_tag_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= subs->from_tag;
7665c794
 	n_query_cols++;
 	
f2fee212
 	result_cols[pres_uri_col = n_result_cols++] = &str_presentity_uri_col;
 	result_cols[rcseq_col = n_result_cols++] = &str_remote_cseq_col;
 	result_cols[lcseq_col = n_result_cols++] = &str_local_cseq_col;
 	result_cols[version_col = n_result_cols++] = &str_version_col;
 	result_cols[rroute_col = n_result_cols++] = &str_record_route_col;
6d7e23db
 
10327c61
 	if(query_fn(rls_db, query_cols, 0, query_vals, result_cols, 
6d7e23db
 			n_query_cols, n_result_cols, 0, &result )< 0)
7665c794
 	{
 		LM_ERR("Can't query db\n");
f968ac71
 		if(result) rls_dbf.free_result(rls_db, result);
7665c794
 		return(-1);
 	}
 
 	if(result == NULL) return(-1);
 
6d7e23db
 	nr_rows = RES_ROW_N(result);
 
 	if (nr_rows == 0)
 	{
 		/* no match - this error might not be for RLS */ 
 		LM_INFO( "update_subs_rlsdb: NO MATCH\n" );
 		rls_dbf.free_result(rls_db, result);
 		return(-1);
 	}
 
 	if (nr_rows != 1)
 	{
 		LM_ERR( "update_subs_rlsdb: TOO MANY MATCHES=%d\n", nr_rows);
 		rls_dbf.free_result(rls_db, result);
 		return(-1);
 	}
 
 	/* get the results and fill in return data structure */
 	rows = RES_ROWS(result);
 	values = ROW_VALUES(rows);
 
f2fee212
 	r_pres_uri = (char *)VAL_STRING(&values[pres_uri_col]);
 	r_remote_cseq = VAL_INT(&values[rcseq_col]);
 	r_local_cseq = VAL_INT(&values[lcseq_col]);
 	r_version = VAL_INT(&values[version_col]);
 	r_record_route = (char *)VAL_STRING(&values[rroute_col]);
6d7e23db
 
9b77e69d
 	if ( r_remote_cseq >= subs->remote_cseq)
 	{
 		LM_DBG("stored cseq= %d\n", r_remote_cseq);
 		rls_dbf.free_result(rls_db, result);
 		return(401); /*stale cseq code */
 	}
 
6d7e23db
 	if(strlen(r_pres_uri) > 0)
 	{
 		subs->pres_uri.s =
 				(char*)pkg_malloc(strlen(r_pres_uri) * sizeof(char));
 		if(subs->pres_uri.s==NULL)
 		{
 			LM_ERR( "Out of Memory\n" );
 			rls_dbf.free_result(rls_db, result);
 			return(-1);
 		}
 		memcpy(subs->pres_uri.s, 
 			r_pres_uri, strlen(r_pres_uri));
 		subs->pres_uri.len= strlen(r_pres_uri);
 	}
 
 	if(strlen(r_record_route) > 0)
 	{
 		subs->record_route.s =
 				(char*)pkg_malloc(strlen(r_record_route) * sizeof(char));
 		if(subs->record_route.s==NULL)
 		{
 			LM_ERR( "Out of Memory\n" );
 			rls_dbf.free_result(rls_db, result);
 			return(-1);
 		}
 		memcpy(subs->record_route.s, 
 			r_record_route, strlen(r_record_route));
 		subs->record_route.len= strlen(r_record_route);
 	}
 
 	subs->local_cseq= r_local_cseq;
 	subs->version= r_version;
 
f968ac71
 	rls_dbf.free_result(rls_db, result);
6d7e23db
 	return 1;
7665c794
 }
 
 /******************************************************************************/
 
6d7e23db
 subs_t *get_dialog_notify_rlsdb(str callid, str to_tag, str from_tag) 
7665c794
 {
67df57c9
  	db_key_t query_cols[4];
 	db_val_t query_vals[4];
b90adb0d
 	db_key_t result_cols[22];
7665c794
 	int n_query_cols = 0, n_result_cols=0;
 	int r_pres_uri_col,r_to_user_col,r_to_domain_col;
 	int r_from_user_col,r_from_domain_col,r_callid_col;
 	int r_to_tag_col,r_from_tag_col,r_socket_info_col;
 	int r_event_id_col,r_local_contact_col,r_contact_col;
b90adb0d
 	int r_record_route_col, r_reason_col, r_event_col;
 	int r_local_cseq_col, r_remote_cseq_col, r_status_col;
 	int r_version_col, r_watcher_user_col, r_watcher_domain_col;
7665c794
 	int r_expires_col;
 	db1_res_t *result= NULL;
  	db_val_t *values;
 	db_row_t *rows;
6d7e23db
 	int nr_rows, size;
7665c794
 	subs_t *dest;
 	event_t parsed_event;
 	str ev_sname;
10327c61
 	db_query_f query_fn = rls_dbf.query_lock ? rls_dbf.query_lock : rls_dbf.query;
7665c794
 
f968ac71
 	if(rls_db == NULL)
7665c794
 	{
 		LM_ERR("null database connection\n");
 		return(NULL);
 	}
 
f968ac71
 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
7665c794
 	{
 		LM_ERR("use table failed\n");
 		return(NULL);
 	}
 	
6d7e23db
 	query_cols[n_query_cols] = &str_callid_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= callid;
7665c794
 	n_query_cols++;
 
6d7e23db
 	query_cols[n_query_cols] = &str_to_tag_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= to_tag;
7665c794
 	n_query_cols++;
 
6d7e23db
 	query_cols[n_query_cols] = &str_from_tag_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.str_val= from_tag;
7665c794
 	n_query_cols++;
67df57c9
 
 	query_cols[n_query_cols] = &str_updated_col;
 	query_vals[n_query_cols].type = DB1_INT;
 	query_vals[n_query_cols].nul = 0;
 	query_vals[n_query_cols].val.int_val= NO_UPDATE_TYPE;
 	n_query_cols++;
7665c794
 	
 	result_cols[r_pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
 	result_cols[r_to_user_col=n_result_cols++] = &str_to_user_col;
 	result_cols[r_to_domain_col=n_result_cols++] = &str_to_domain_col;
b90adb0d
 	result_cols[r_from_user_col=n_result_cols++] = &str_from_user_col;
 	result_cols[r_from_domain_col=n_result_cols++] = &str_from_domain_col;
 	result_cols[r_watcher_user_col=n_result_cols++] = &str_watcher_username_col;
 	result_cols[r_watcher_domain_col=n_result_cols++] = &str_watcher_domain_col;
7665c794
 	result_cols[r_callid_col=n_result_cols++] = &str_callid_col;
 	result_cols[r_to_tag_col=n_result_cols++] = &str_to_tag_col;
 	result_cols[r_from_tag_col=n_result_cols++] = &str_from_tag_col;
 	result_cols[r_socket_info_col=n_result_cols++] = &str_socket_info_col;
 	result_cols[r_event_id_col=n_result_cols++] = &str_event_id_col;
 	result_cols[r_local_contact_col=n_result_cols++] = &str_local_contact_col;
 	result_cols[r_contact_col=n_result_cols++] = &str_contact_col;
 	result_cols[r_record_route_col=n_result_cols++] = &str_record_route_col;
 	result_cols[r_reason_col=n_result_cols++] = &str_reason_col;
 	result_cols[r_event_col=n_result_cols++] = &str_event_col;
 	result_cols[r_local_cseq_col=n_result_cols++] = &str_local_cseq_col;
 	result_cols[r_remote_cseq_col=n_result_cols++] = &str_remote_cseq_col;
 	result_cols[r_status_col=n_result_cols++] = &str_status_col;
 	result_cols[r_version_col=n_result_cols++] = &str_version_col;
 	result_cols[r_expires_col=n_result_cols++] = &str_expires_col;
 
10327c61
 	if(query_fn(rls_db, query_cols, 0, query_vals, result_cols, 
7665c794
 				n_query_cols, n_result_cols, 0, &result )< 0)
 	{
 		LM_ERR("Can't query db\n");
f968ac71
 		if(result) rls_dbf.free_result(rls_db, result);
7665c794
 		return(NULL);
 	}
 
 	if(result == NULL) return(NULL);
 
 	nr_rows = RES_ROW_N(result);
 
 	if (nr_rows == 0)
 	{
 		/* no match */ 
0c352ed5
 		LM_INFO( "get_dialog_rlsdb No matching records\n" );
f968ac71
 		rls_dbf.free_result(rls_db, result);
7665c794
 		return(NULL);
 	}
 
 	if (nr_rows != 1)
 	{
0c352ed5
 		LM_ERR( "get_dialog_rlsdb multiple matching records\n" );
f968ac71
 		rls_dbf.free_result(rls_db, result);
7665c794
 		return(NULL);
 	}
 
 	/* get the results and fill in return data structure */
6d7e23db
 	rows = RES_ROWS(result);
 	values = ROW_VALUES(rows);
7665c794
 
6d7e23db
 	size= sizeof(subs_t) +
 		( strlen(VAL_STRING(values+r_pres_uri_col))
 		+ strlen(VAL_STRING(values+r_to_user_col))
 		+ strlen(VAL_STRING(values+r_to_domain_col))
 		+ strlen(VAL_STRING(values+r_from_user_col))
 		+ strlen(VAL_STRING(values+r_from_domain_col))
b90adb0d
 		+ strlen(VAL_STRING(values+r_watcher_user_col))
 		+ strlen(VAL_STRING(values+r_watcher_domain_col))
6d7e23db
 		+ strlen(VAL_STRING(values+r_to_tag_col))
 		+ strlen(VAL_STRING(values+r_from_tag_col))
 		+ strlen(VAL_STRING(values+r_callid_col))
 		+ strlen(VAL_STRING(values+r_socket_info_col))
 		+ strlen(VAL_STRING(values+r_local_contact_col))
 		+ strlen(VAL_STRING(values+r_contact_col))
 		+ strlen(VAL_STRING(values+r_record_route_col))
 		+ strlen(VAL_STRING(values+r_event_id_col))
 		+ strlen(VAL_STRING(values+r_reason_col)))*sizeof(char);
 
 	dest= (subs_t*)pkg_malloc(size);
7665c794
 	
6d7e23db
 	if(dest== NULL)
 	{
 		LM_ERR( "Can't allocate memory\n" );
 		rls_dbf.free_result(rls_db, result);
 		return(NULL);
 	}
 	memset(dest, 0, size);
 	size= sizeof(subs_t);
7665c794
 
6d7e23db
 	CONT_COPYDB(dest, dest->pres_uri, VAL_STRING(values+r_pres_uri_col))
 	CONT_COPYDB(dest, dest->to_user, VAL_STRING(values+r_to_user_col))
 	CONT_COPYDB(dest, dest->to_domain, VAL_STRING(values+r_to_domain_col))
 	CONT_COPYDB(dest, dest->from_user, VAL_STRING(values+r_from_user_col))
 	CONT_COPYDB(dest, dest->from_domain, VAL_STRING(values+r_from_domain_col))
b90adb0d
 	CONT_COPYDB(dest, dest->watcher_user, VAL_STRING(values+r_watcher_user_col))
 	CONT_COPYDB(dest, dest->watcher_domain, VAL_STRING(values+r_watcher_domain_col))
6d7e23db
 	CONT_COPYDB(dest, dest->to_tag, VAL_STRING(values+r_to_tag_col))
 	CONT_COPYDB(dest, dest->from_tag, VAL_STRING(values+r_from_tag_col))
 	CONT_COPYDB(dest, dest->callid, VAL_STRING(values+r_callid_col))
 	CONT_COPYDB(dest, dest->sockinfo_str, VAL_STRING(values+r_socket_info_col))
 	CONT_COPYDB(dest, dest->local_contact, VAL_STRING(values+r_local_contact_col))
 	CONT_COPYDB(dest, dest->contact, VAL_STRING(values+r_contact_col))
 	CONT_COPYDB(dest, dest->record_route, VAL_STRING(values+r_record_route_col))
7665c794
 
6d7e23db
 	if(strlen(VAL_STRING(values+r_event_id_col)) > 0)
 		CONT_COPYDB(dest, dest->event_id, VAL_STRING(values+r_event_id_col))
7665c794
 
6d7e23db
 	if(strlen(VAL_STRING(values+r_reason_col)) > 0)
 		CONT_COPYDB(dest, dest->reason, VAL_STRING(values+r_reason_col))
7665c794
 
6d7e23db
 	ev_sname.s= (char *)VAL_STRING(values+r_event_col);
 	ev_sname.len= strlen(ev_sname.s);
7665c794
 
6d7e23db
 	dest->event = pres_contains_event(&ev_sname, &parsed_event);
7665c794
 
6d7e23db
 	if(dest->event == NULL)
 		LM_ERR("event not found and set to NULL\n");
7665c794
 
6d7e23db
 	dest->local_cseq= VAL_INT(values+r_local_cseq_col);
 	dest->remote_cseq= VAL_INT(values+r_remote_cseq_col);
 	dest->status= VAL_INT(values+r_status_col);
 	dest->version= VAL_INT(values+r_version_col);
 	dest->expires= VAL_INT(values+r_expires_col);
7665c794
 
f968ac71
 	rls_dbf.free_result(rls_db, result);
7665c794
 
 	return(dest);
 }
 
 /******************************************************************************/