1 /*
2  * rls db - RLS database support
3  *
4  * Copyright (C) 2011 Crocodile RCS Ltd
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22 
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "../../core/mem/mem.h"
29 #include "../../core/mem/shm_mem.h"
30 #include "../../core/dprint.h"
31 #include "../../lib/srdb1/db.h"
32 #include "../../core/parser/msg_parser.h"
33 #include "../../core/parser/parse_from.h"
34 #include "../../core/hashes.h"
35 
36 #include "rls.h"
37 
38 #define CONT_COPYDB(buf, dest, source)\
39 	do{ \
40 		dest.s= (char*)buf+ size;\
41 		memcpy(dest.s, source, strlen(source));\
42 		dest.len= strlen(source);\
43 		size+= strlen(source); \
44 	} while(0)
45 
46 /* database connection */
47 extern db1_con_t *rls_db;
48 extern db_func_t rls_dbf;
49 
50 extern void update_a_sub(subs_t *subs_copy );
51 
52 /******************************************************************************/
53 
rls_new_shtable(int hash_size)54 shtable_t rls_new_shtable(int hash_size)
55 {
56 	LM_ERR( "rls_new_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
57 	return(NULL);
58 }
59 
60 /******************************************************************************/
61 
rls_destroy_shtable(shtable_t htable,int hash_size)62 void rls_destroy_shtable(shtable_t htable, int hash_size)
63 {
64 	LM_ERR( "rls_destroy_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
65 }
66 
67 /******************************************************************************/
68 
rls_insert_shtable(shtable_t htable,unsigned int hash_code,subs_t * subs)69 int rls_insert_shtable(shtable_t htable,unsigned int hash_code, subs_t* subs)
70 {
71 	LM_ERR( "rls_insert_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
72 	return(-1);
73 }
74 
75 /******************************************************************************/
76 
rls_search_shtable(shtable_t htable,str callid,str to_tag,str from_tag,unsigned int hash_code)77 subs_t* rls_search_shtable(shtable_t htable,str callid,str to_tag,
78 		str from_tag,unsigned int hash_code)
79 {
80 	LM_ERR( "rls_search_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
81 	return(NULL);
82 }
83 
84 /******************************************************************************/
85 
rls_delete_shtable(shtable_t htable,unsigned int hash_code,subs_t * subs)86 int rls_delete_shtable(shtable_t htable,unsigned int hash_code, subs_t* subs)
87 {
88 	LM_ERR( "rls_delete_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
89 	return(-1);
90 }
91 
92 /******************************************************************************/
93 
rls_update_shtable(shtable_t htable,unsigned int hash_code,subs_t * subs,int type)94 int rls_update_shtable(shtable_t htable,unsigned int hash_code,
95 		subs_t* subs, int type)
96 {
97 	LM_ERR( "rls_update_shtable shouldn't be called in RLS_DB_ONLY mode\n" );
98 	return(-1);
99 }
100 
101 /******************************************************************************/
102 
rls_update_db_subs_timer(db1_con_t * db,db_func_t * dbf,shtable_t hash_table,int htable_size,int no_lock,handle_expired_func_t handle_expired_func)103 void rls_update_db_subs_timer(db1_con_t *db,db_func_t *dbf, shtable_t hash_table,
104 	int htable_size, int no_lock, handle_expired_func_t handle_expired_func)
105 {
106 	LM_ERR( "rls_update_db_subs_timer shouldn't be called in RLS_DB_ONLY mode\n" );
107 }
108 
109 /******************************************************************************/
110 /******************************************************************************/
111 
delete_expired_subs_rlsdb(void)112 int delete_expired_subs_rlsdb( void )
113 
114 {
115 	db_key_t query_cols[3], result_cols[3], update_cols[1];
116 	db_val_t query_vals[3], update_vals[1], *values;
117 	db_op_t query_ops[2];
118 	db_row_t *rows;
119 	db1_res_t *result = NULL;
120 	int n_query_cols = 0, n_result_cols = 0;
121 	int r_callid_col = 0, r_to_tag_col = 0, r_from_tag_col = 0;
122 	int i, nr_rows;
123 	subs_t subs;
124 	str rlsubs_did = {0, 0};
125 	db_query_f query_fn = rls_dbf.query_lock ? rls_dbf.query_lock : rls_dbf.query;
126 
127 	if(rls_db == NULL)
128 	{
129 		LM_ERR("null database connection\n");
130 		goto error;
131 	}
132 
133 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
134 	{
135 		LM_ERR("use table failed\n");
136 		goto error;
137 	}
138 
139 	query_cols[n_query_cols]= &str_expires_col;
140 	query_vals[n_query_cols].type = DB1_INT;
141 	query_vals[n_query_cols].nul = 0;
142 	query_vals[n_query_cols].val.int_val= (int)time(NULL) - rls_expires_offset;
143 	query_ops[n_query_cols]= OP_LT;
144 	n_query_cols++;
145 
146 	query_cols[n_query_cols]= &str_updated_col;
147 	query_vals[n_query_cols].type = DB1_INT;
148 	query_vals[n_query_cols].nul = 0;
149 	query_vals[n_query_cols].val.int_val= NO_UPDATE_TYPE;
150 	query_ops[n_query_cols]= OP_EQ;
151 	n_query_cols++;
152 
153 	result_cols[r_callid_col=n_result_cols++] = &str_callid_col;
154 	result_cols[r_to_tag_col=n_result_cols++] = &str_to_tag_col;
155 	result_cols[r_from_tag_col=n_result_cols++] = &str_from_tag_col;
156 
157 	if (rls_dbf.start_transaction)
158 	{
159 		if (rls_dbf.start_transaction(rls_db, DB_LOCKING_WRITE) < 0)
160 		{
161 			LM_ERR("in start_transaction\n");
162 			goto error;
163 		}
164 	}
165 
166 	if(query_fn(rls_db, query_cols, query_ops, query_vals, result_cols,
167 				n_query_cols, n_result_cols, 0, &result )< 0)
168 	{
169 		LM_ERR("Can't query db\n");
170 		goto error;
171 	}
172 
173 	if(result == NULL) goto error;
174 
175 	rows = RES_ROWS(result);
176 	nr_rows = RES_ROW_N(result);
177 
178 	for (i = 0; i < nr_rows; i++)
179 	{
180 		memset(&subs, 0, sizeof(subs_t));
181 		values = ROW_VALUES(&rows[i]);
182 
183 		subs.callid.s = (char *) VAL_STRING(&values[r_callid_col]);
184 		subs.callid.len = strlen(subs.callid.s);
185 		subs.to_tag.s = (char *) VAL_STRING(&values[r_to_tag_col]);
186 		subs.to_tag.len = strlen(subs.to_tag.s);
187 		subs.from_tag.s = (char *) VAL_STRING(&values[r_from_tag_col]);
188 		subs.from_tag.len = strlen(subs.from_tag.s);
189 
190 		if (CONSTR_RLSUBS_DID(&subs, &rlsubs_did) < 0)
191 		{
192 			LM_ERR("cannot build rls subs did\n");
193 			goto error;
194 		}
195 		subs.updated = core_hash(&rlsubs_did, NULL, 0) %
196 			(waitn_time * rls_notifier_poll_rate * rls_notifier_processes);
197 
198 		n_query_cols = 0;
199 
200 		query_cols[n_query_cols] = &str_callid_col;
201 		query_vals[n_query_cols].type = DB1_STR;
202 		query_vals[n_query_cols].nul = 0;
203 		query_vals[n_query_cols].val.str_val = subs.callid;
204 		n_query_cols++;
205 
206 		query_cols[n_query_cols] = &str_to_tag_col;
207 		query_vals[n_query_cols].type = DB1_STR;
208 		query_vals[n_query_cols].nul = 0;
209 		query_vals[n_query_cols].val.str_val = subs.to_tag;
210 		n_query_cols++;
211 
212 		query_cols[n_query_cols] = &str_from_tag_col;
213 		query_vals[n_query_cols].type = DB1_STR;
214 		query_vals[n_query_cols].nul = 0;
215 		query_vals[n_query_cols].val.str_val = subs.from_tag;
216 		n_query_cols++;
217 
218 		update_cols[0] = &str_updated_col;
219 		update_vals[0].type = DB1_INT;
220 		update_vals[0].nul = 0;
221 		update_vals[0].val.int_val = subs.updated;
222 
223 		if(rls_dbf.update(rls_db, query_cols, 0, query_vals,
224 			update_cols,update_vals,n_query_cols, 1) < 0)
225 		{
226 			LM_ERR("db update failed for expired subs\n");
227 			goto error;
228 		}
229 
230 		pkg_free(rlsubs_did.s);
231 		rlsubs_did.s = NULL;
232 	}
233 
234 	rls_dbf.free_result(rls_db, result);
235 	result = NULL;
236 
237 	if (rls_dbf.end_transaction)
238 	{
239 		if (rls_dbf.end_transaction(rls_db) < 0)
240 		{
241 			LM_ERR("in end_transaction\n");
242 			goto error;
243 		}
244 	}
245 
246 	return 1;
247 
248 error:
249 	if (result) rls_dbf.free_result(rls_db, result);
250 	if (rlsubs_did.s) pkg_free(rlsubs_did.s);
251 
252 	if (rls_dbf.abort_transaction)
253 	{
254 		if (rls_dbf.abort_transaction(rls_db) < 0)
255 			LM_ERR("in abort_transaction\n");
256 	}
257 
258 	return -1;
259 }
260 
261 /******************************************************************************/
262 
delete_rlsdb(str * callid,str * to_tag,str * from_tag)263 int delete_rlsdb( str *callid, str *to_tag, str *from_tag )
264 
265 {
266 	int rval;
267 	db_key_t query_cols[3];
268 	db_val_t query_vals[3];
269 	int n_query_cols = 0;
270 
271 	if(rls_db == NULL)
272 	{
273 		LM_ERR("null database connection\n");
274 		return(-1);
275 	}
276 
277 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
278 	{
279 		LM_ERR("use table failed\n");
280 		return(-1);
281 	}
282 
283 	query_cols[n_query_cols] = &str_callid_col;
284 	query_vals[n_query_cols].type = DB1_STR;
285 	query_vals[n_query_cols].nul = 0;
286 	query_vals[n_query_cols].val.str_val= *callid;
287 	n_query_cols++;
288 
289 	query_cols[n_query_cols] = &str_to_tag_col;
290 	query_vals[n_query_cols].type = DB1_STR;
291 	query_vals[n_query_cols].nul = 0;
292 	query_vals[n_query_cols].val.str_val= *to_tag;
293 	n_query_cols++;
294 
295 	if (from_tag)
296 	{
297 		query_cols[n_query_cols] = &str_from_tag_col;
298 		query_vals[n_query_cols].type = DB1_STR;
299 		query_vals[n_query_cols].nul = 0;
300 		query_vals[n_query_cols].val.str_val= *from_tag;
301 		n_query_cols++;
302 	}
303 
304 	rval = rls_dbf.delete(rls_db, query_cols, 0, query_vals, n_query_cols);
305 
306 	if (rval < 0)
307 	{
308 		LM_ERR("Can't delete in db\n");
309 		return(-1);
310 	}
311 
312 	return(1);
313 }
314 
315 /******************************************************************************/
316 
update_dialog_notify_rlsdb(subs_t * subs)317 int update_dialog_notify_rlsdb(subs_t *subs)
318 
319 {
320 	db_key_t query_cols[3];
321 	db_val_t query_vals[3];
322 	db_key_t data_cols[3];
323 	db_val_t data_vals[3];
324 	int n_query_cols = 0, n_data_cols=0;
325 
326 	if (subs==NULL) return(-1);
327 
328 	if(rls_db == NULL)
329 	{
330 		LM_ERR("null database connection\n");
331 		return(-1);
332 	}
333 
334 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
335 	{
336 		LM_ERR("use table failed\n");
337 		return(-1);
338 	}
339 
340 	subs->local_cseq++;
341 	subs->version++;
342 
343 	query_cols[n_query_cols] = &str_callid_col;
344 	query_vals[n_query_cols].type = DB1_STR;
345 	query_vals[n_query_cols].nul = 0;
346 	query_vals[n_query_cols].val.str_val= subs->callid;
347 	n_query_cols++;
348 
349 	query_cols[n_query_cols] = &str_to_tag_col;
350 	query_vals[n_query_cols].type = DB1_STR;
351 	query_vals[n_query_cols].nul = 0;
352 	query_vals[n_query_cols].val.str_val= subs->to_tag;
353 	n_query_cols++;
354 
355 	query_cols[n_query_cols] = &str_from_tag_col;
356 	query_vals[n_query_cols].type = DB1_STR;
357 	query_vals[n_query_cols].nul = 0;
358 	query_vals[n_query_cols].val.str_val= subs->from_tag;
359 	n_query_cols++;
360 
361 	data_cols[n_data_cols]=&str_local_cseq_col;
362 	data_vals[n_data_cols].type = DB1_INT;
363 	data_vals[n_data_cols].nul = 0;
364 	data_vals[n_data_cols].val.int_val= subs->local_cseq;
365 	n_data_cols++;
366 
367 	data_cols[n_data_cols]=&str_version_col;
368 	data_vals[n_data_cols].type = DB1_INT;
369 	data_vals[n_data_cols].nul = 0;
370 	data_vals[n_data_cols].val.int_val= subs->version;
371 	n_data_cols++;
372 
373 	data_cols[n_data_cols] =&str_status_col;
374 	data_vals[n_data_cols].type = DB1_INT;
375 	data_vals[n_data_cols].nul = 0;
376 	data_vals[n_data_cols].val.int_val= subs->status;
377 	n_data_cols++;
378 
379 	if(rls_dbf.update(rls_db, query_cols, 0, query_vals,
380 			data_cols,data_vals,n_query_cols,n_data_cols) < 0)
381 	{
382 		LM_ERR("Failed update db\n");
383 		return(-1);
384 	}
385 
386 	return(0);
387 }
388 
389 /******************************************************************************/
390 
update_all_subs_rlsdb(str * watcher_user,str * watcher_domain,str * evt)391 int update_all_subs_rlsdb(str *watcher_user, str *watcher_domain, str *evt)
392 {
393 	db_key_t query_cols[3];
394 	db_val_t query_vals[3];
395 	db_key_t result_cols[20];
396 	int n_query_cols = 0, n_result_cols=0;
397 	int r_pres_uri_col, r_callid_col, r_to_tag_col, r_from_tag_col;
398 	int r_event_col, r_expires_col;
399 	db1_res_t *result= NULL;
400 	db_val_t *values;
401 	db_row_t *rows;
402 	int nr_rows, size, loop;
403 	subs_t *dest;
404 	event_t parsed_event;
405 
406 	if(rls_db == NULL)
407 	{
408 		LM_ERR("null database connection\n");
409 		return(-1);
410 	}
411 
412 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
413 	{
414 		LM_ERR("use table failed\n");
415 		return(-1);
416 	}
417 
418 	query_cols[n_query_cols] = &str_watcher_username_col;
419 	query_vals[n_query_cols].type = DB1_STR;
420 	query_vals[n_query_cols].nul = 0;
421 	query_vals[n_query_cols].val.str_val= *watcher_user;
422 	n_query_cols++;
423 
424 	query_cols[n_query_cols] = &str_watcher_domain_col;
425 	query_vals[n_query_cols].type = DB1_STR;
426 	query_vals[n_query_cols].nul = 0;
427 	query_vals[n_query_cols].val.str_val= *watcher_domain;
428 	n_query_cols++;
429 
430 	query_cols[n_query_cols] = &str_event_col;
431 	query_vals[n_query_cols].type = DB1_STR;
432 	query_vals[n_query_cols].nul = 0;
433 	query_vals[n_query_cols].val.str_val= *evt;
434 	n_query_cols++;
435 
436 	result_cols[r_pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
437 	result_cols[r_callid_col=n_result_cols++] = &str_callid_col;
438 	result_cols[r_to_tag_col=n_result_cols++] = &str_to_tag_col;
439 	result_cols[r_from_tag_col=n_result_cols++] = &str_from_tag_col;
440 	result_cols[r_event_col=n_result_cols++] = &str_event_col;
441 	result_cols[r_expires_col=n_result_cols++] = &str_expires_col;
442 
443 	if(rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols,
444 				n_query_cols, n_result_cols, 0, &result )< 0)
445 	{
446 		LM_ERR("Can't query db\n");
447 		if(result) rls_dbf.free_result(rls_db, result);
448 		return(-1);
449 	}
450 
451 	if(result == NULL) return(-1);
452 
453 	nr_rows = RES_ROW_N(result);
454 
455 	rows = RES_ROWS(result);
456 	/* get the results and fill in return data structure */
457 	for (loop=0; loop <nr_rows; loop++)
458 	{
459 		values = ROW_VALUES(&rows[loop]);
460 
461 		size= sizeof(subs_t) +
462 			( strlen(VAL_STRING(values+r_pres_uri_col))
463 			+ strlen(VAL_STRING(values+r_to_tag_col))
464 			+ strlen(VAL_STRING(values+r_from_tag_col))
465 			+ strlen(VAL_STRING(values+r_callid_col)))*sizeof(char);
466 
467 		dest= (subs_t*)pkg_malloc(size);
468 
469 		if(dest== NULL)
470 		{
471 			LM_ERR( "Can't allocate memory\n" );
472 			rls_dbf.free_result(rls_db, result);
473 			return(-1);
474 		}
475 		memset(dest, 0, size);
476 		size= sizeof(subs_t);
477 
478 		CONT_COPYDB(dest, dest->pres_uri, VAL_STRING(values+r_pres_uri_col));
479 		CONT_COPYDB(dest, dest->to_tag, VAL_STRING(values+r_to_tag_col));
480 		CONT_COPYDB(dest, dest->from_tag, VAL_STRING(values+r_from_tag_col));
481 		CONT_COPYDB(dest, dest->callid, VAL_STRING(values+r_callid_col));
482 
483 		dest->event = pres_contains_event(evt, &parsed_event);
484 		if(dest->event == NULL)
485 		{
486 			LM_ERR("event not found and set to NULL\n");
487 		}
488 
489 		dest->expires= VAL_INT(values+r_expires_col);
490 		dest->watcher_user.s= watcher_user->s;
491 		dest->watcher_user.len= watcher_user->len;
492 		dest->watcher_domain.s= watcher_domain->s;
493 		dest->watcher_domain.len= watcher_domain->len;
494 
495 		update_a_sub(dest);
496 	}
497 
498 	rls_dbf.free_result(rls_db, result);
499 	return(1);
500 }
501 
502 /******************************************************************************/
503 
update_dialog_subscribe_rlsdb(subs_t * subs)504 int update_dialog_subscribe_rlsdb(subs_t *subs)
505 
506 {
507 	db_key_t query_cols[3];
508 	db_val_t query_vals[3];
509 	db_key_t data_cols[3];
510 	db_val_t data_vals[3];
511 	int n_query_cols = 0, n_data_cols=0;
512 
513 	if (subs==NULL) return(-1);
514 
515 	if(rls_db == NULL)
516 	{
517 		LM_ERR("null database connection\n");
518 		return(-1);
519 	}
520 
521 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
522 	{
523 		LM_ERR("use table failed\n");
524 		return(-1);
525 	}
526 
527 	query_cols[n_query_cols] = &str_callid_col;
528 	query_vals[n_query_cols].type = DB1_STR;
529 	query_vals[n_query_cols].nul = 0;
530 	query_vals[n_query_cols].val.str_val= subs->callid;
531 	n_query_cols++;
532 
533 	query_cols[n_query_cols] = &str_to_tag_col;
534 	query_vals[n_query_cols].type = DB1_STR;
535 	query_vals[n_query_cols].nul = 0;
536 	query_vals[n_query_cols].val.str_val= subs->to_tag;
537 	n_query_cols++;
538 
539 	query_cols[n_query_cols] = &str_from_tag_col;
540 	query_vals[n_query_cols].type = DB1_STR;
541 	query_vals[n_query_cols].nul = 0;
542 	query_vals[n_query_cols].val.str_val= subs->from_tag;
543 	n_query_cols++;
544 
545 	data_cols[n_data_cols] = &str_expires_col;
546 	data_vals[n_data_cols].type = DB1_INT;
547 	data_vals[n_data_cols].nul = 0;
548 	data_vals[n_data_cols].val.int_val = subs->expires + (int)time(NULL);
549 	n_data_cols++;
550 
551 	data_cols[n_data_cols] = &str_remote_cseq_col;
552 	data_vals[n_data_cols].type = DB1_INT;
553 	data_vals[n_data_cols].nul = 0;
554 	data_vals[n_data_cols].val.int_val= subs->remote_cseq;
555 	n_data_cols++;
556 
557 	data_cols[n_data_cols] = &str_updated_col;
558 	data_vals[n_data_cols].type = DB1_INT;
559 	data_vals[n_data_cols].nul = 0;
560 	data_vals[n_data_cols].val.int_val= subs->updated;
561 	n_data_cols++;
562 
563 	if(rls_dbf.update(rls_db, query_cols, 0, query_vals,
564 				data_cols,data_vals,n_query_cols,n_data_cols) < 0)
565 	{
566 		LM_ERR("Failed update db\n");
567 		return(-1);
568 	}
569 
570 	return(0);
571 }
572 
573 /******************************************************************************/
574 
insert_rlsdb(subs_t * s)575 int insert_rlsdb( subs_t *s )
576 
577 {
578 	db_key_t data_cols[23];
579 	db_val_t data_vals[23];
580 	int n_data_cols = 0;
581 
582 	if (s==NULL) return(-1);
583 
584 	if(rls_db == NULL)
585 	{
586 		LM_ERR("null database connection\n");
587 		return(-1);
588 	}
589 
590 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
591 	{
592 		LM_ERR("use table failed\n");
593 		return(-1);
594 	}
595 
596 	data_cols[n_data_cols] = &str_presentity_uri_col;
597 	data_vals[n_data_cols].type = DB1_STR;
598 	data_vals[n_data_cols].nul = 0;
599 	data_vals[n_data_cols].val.str_val= s->pres_uri;
600 	n_data_cols++;
601 
602 	data_cols[n_data_cols] = &str_callid_col;
603 	data_vals[n_data_cols].type = DB1_STR;
604 	data_vals[n_data_cols].nul = 0;
605 	data_vals[n_data_cols].val.str_val= s->callid;
606 	n_data_cols++;
607 
608 	data_cols[n_data_cols] = &str_to_tag_col;
609 	data_vals[n_data_cols].type = DB1_STR;
610 	data_vals[n_data_cols].nul = 0;
611 	data_vals[n_data_cols].val.str_val= s->to_tag;
612 	n_data_cols++;
613 
614 	data_cols[n_data_cols] = &str_from_tag_col;
615 	data_vals[n_data_cols].type = DB1_STR;
616 	data_vals[n_data_cols].nul = 0;
617 	data_vals[n_data_cols].val.str_val= s->from_tag;
618 	n_data_cols++;
619 
620 	data_cols[n_data_cols] = &str_to_user_col;
621 	data_vals[n_data_cols].type = DB1_STR;
622 	data_vals[n_data_cols].nul = 0;
623 	data_vals[n_data_cols].val.str_val = s->to_user;
624 	n_data_cols++;
625 
626 	data_cols[n_data_cols] = &str_to_domain_col;
627 	data_vals[n_data_cols].type = DB1_STR;
628 	data_vals[n_data_cols].nul = 0;
629 	data_vals[n_data_cols].val.str_val = s->to_domain;
630 	n_data_cols++;
631 
632 	data_cols[n_data_cols] = &str_from_user_col;
633 	data_vals[n_data_cols].type = DB1_STR;
634 	data_vals[n_data_cols].nul = 0;
635 	data_vals[n_data_cols].val.str_val = s->from_user;
636 	n_data_cols++;
637 
638 	data_cols[n_data_cols] = &str_from_domain_col;
639 	data_vals[n_data_cols].type = DB1_STR;
640 	data_vals[n_data_cols].nul = 0;
641 	data_vals[n_data_cols].val.str_val = s->from_domain;
642 	n_data_cols++;
643 
644 	data_cols[n_data_cols] = &str_watcher_username_col;
645 	data_vals[n_data_cols].type = DB1_STR;
646 	data_vals[n_data_cols].nul = 0;
647 	data_vals[n_data_cols].val.str_val = s->watcher_user;
648 	n_data_cols++;
649 
650 	data_cols[n_data_cols] = &str_watcher_domain_col;
651 	data_vals[n_data_cols].type = DB1_STR;
652 	data_vals[n_data_cols].nul = 0;
653 	data_vals[n_data_cols].val.str_val = s->watcher_domain;
654 	n_data_cols++;
655 
656 	data_cols[n_data_cols] = &str_event_col;
657 	data_vals[n_data_cols].type = DB1_STR;
658 	data_vals[n_data_cols].nul = 0;
659 	data_vals[n_data_cols].val.str_val = s->event->name;
660 	n_data_cols++;
661 
662 	data_cols[n_data_cols] = &str_event_id_col;
663 	data_vals[n_data_cols].type = DB1_STR;
664 	data_vals[n_data_cols].nul = 0;
665 	data_vals[n_data_cols].val.str_val = s->event_id;
666 	n_data_cols++;
667 
668 	data_cols[n_data_cols]=&str_local_cseq_col;
669 	data_vals[n_data_cols].type = DB1_INT;
670 	data_vals[n_data_cols].nul = 0;
671 	data_vals[n_data_cols].val.int_val= s->local_cseq;
672 	n_data_cols++;
673 
674 	data_cols[n_data_cols]=&str_remote_cseq_col;
675 	data_vals[n_data_cols].type = DB1_INT;
676 	data_vals[n_data_cols].nul = 0;
677 	data_vals[n_data_cols].val.int_val= s->remote_cseq;
678 	n_data_cols++;
679 
680 	data_cols[n_data_cols] =&str_expires_col;
681 	data_vals[n_data_cols].type = DB1_INT;
682 	data_vals[n_data_cols].nul = 0;
683 	data_vals[n_data_cols].val.int_val = s->expires + (int)time(NULL);
684 	n_data_cols++;
685 
686 	data_cols[n_data_cols] =&str_status_col;
687 	data_vals[n_data_cols].type = DB1_INT;
688 	data_vals[n_data_cols].nul = 0;
689 	data_vals[n_data_cols].val.int_val= s->status;
690 	n_data_cols++;
691 
692 	data_cols[n_data_cols] =&str_reason_col;
693 	data_vals[n_data_cols].type = DB1_STR;
694 	data_vals[n_data_cols].nul = 0;
695 	data_vals[n_data_cols].val.str_val= s->reason;
696 	n_data_cols++;
697 
698 	data_cols[n_data_cols] =&str_record_route_col;
699 	data_vals[n_data_cols].type = DB1_STR;
700 	data_vals[n_data_cols].nul = 0;
701 	data_vals[n_data_cols].val.str_val = s->record_route;
702 	n_data_cols++;
703 
704 	data_cols[n_data_cols] =&str_contact_col;
705 	data_vals[n_data_cols].type = DB1_STR;
706 	data_vals[n_data_cols].nul = 0;
707 	data_vals[n_data_cols].val.str_val = s->contact;
708 	n_data_cols++;
709 
710 	data_cols[n_data_cols] =&str_local_contact_col;
711 	data_vals[n_data_cols].type = DB1_STR;
712 	data_vals[n_data_cols].nul = 0;
713 	data_vals[n_data_cols].val.str_val = s->local_contact;
714 	n_data_cols++;
715 
716 	data_cols[n_data_cols] =&str_socket_info_col;
717 	data_vals[n_data_cols].type = DB1_STR;
718 	data_vals[n_data_cols].nul = 0;
719 	data_vals[n_data_cols].val.str_val= s->sockinfo_str;
720 	n_data_cols++;
721 
722 	data_cols[n_data_cols]=&str_version_col;
723 	data_vals[n_data_cols].type = DB1_INT;
724 	data_vals[n_data_cols].nul = 0;
725 	data_vals[n_data_cols].val.int_val= s->version;
726 	n_data_cols++;
727 
728 	data_cols[n_data_cols]=&str_updated_col;
729 	data_vals[n_data_cols].type = DB1_INT;
730 	data_vals[n_data_cols].nul = 0;
731 	data_vals[n_data_cols].val.int_val= s->updated;
732 	n_data_cols++;
733 
734 	if(rls_dbf.insert(rls_db, data_cols, data_vals, n_data_cols) < 0)
735 	{
736 		LM_ERR("db insert failed\n");
737 		return(-1);
738 	}
739 
740 	return(0);
741 }
742 
743 /******************************************************************************/
744 
get_dialog_subscribe_rlsdb(subs_t * subs)745 int get_dialog_subscribe_rlsdb(subs_t *subs)
746 
747 {
748 	db1_res_t *result= NULL;
749 	db_key_t query_cols[3];
750 	db_val_t query_vals[3], *values;
751 	db_key_t result_cols[5];
752 	db_row_t *rows;
753 	int n_query_cols = 0, n_result_cols = 0;
754 	int pres_uri_col, rcseq_col, lcseq_col, version_col, rroute_col;
755 	int nr_rows;
756 	int r_remote_cseq, r_local_cseq, r_version;
757 	char *r_pres_uri, *r_record_route;
758 	db_query_f query_fn = rls_dbf.query_lock ? rls_dbf.query_lock : rls_dbf.query;
759 
760 	if(rls_db == NULL)
761 	{
762 		LM_ERR("null database connection\n");
763 		return(-1);
764 	}
765 
766 	if (subs == NULL)
767 	{
768 		LM_ERR("null subscriptions\n");
769 		return(-1);
770 	}
771 
772 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
773 	{
774 		LM_ERR("use table failed\n");
775 		return(-1);
776 	}
777 
778 	query_cols[n_query_cols] = &str_callid_col;
779 	query_vals[n_query_cols].type = DB1_STR;
780 	query_vals[n_query_cols].nul = 0;
781 	query_vals[n_query_cols].val.str_val= subs->callid;
782 	n_query_cols++;
783 
784 	query_cols[n_query_cols] = &str_to_tag_col;
785 	query_vals[n_query_cols].type = DB1_STR;
786 	query_vals[n_query_cols].nul = 0;
787 	query_vals[n_query_cols].val.str_val= subs->to_tag;
788 	n_query_cols++;
789 
790 	query_cols[n_query_cols] = &str_from_tag_col;
791 	query_vals[n_query_cols].type = DB1_STR;
792 	query_vals[n_query_cols].nul = 0;
793 	query_vals[n_query_cols].val.str_val= subs->from_tag;
794 	n_query_cols++;
795 
796 	result_cols[pres_uri_col = n_result_cols++] = &str_presentity_uri_col;
797 	result_cols[rcseq_col = n_result_cols++] = &str_remote_cseq_col;
798 	result_cols[lcseq_col = n_result_cols++] = &str_local_cseq_col;
799 	result_cols[version_col = n_result_cols++] = &str_version_col;
800 	result_cols[rroute_col = n_result_cols++] = &str_record_route_col;
801 
802 	if(query_fn(rls_db, query_cols, 0, query_vals, result_cols,
803 			n_query_cols, n_result_cols, 0, &result )< 0)
804 	{
805 		LM_ERR("Can't query db\n");
806 		if(result) rls_dbf.free_result(rls_db, result);
807 		return(-1);
808 	}
809 
810 	if(result == NULL) return(-1);
811 
812 	nr_rows = RES_ROW_N(result);
813 
814 	if (nr_rows == 0)
815 	{
816 		/* no match - this error might not be for RLS */
817 		LM_INFO( "update_subs_rlsdb: NO MATCH\n" );
818 		rls_dbf.free_result(rls_db, result);
819 		return(-1);
820 	}
821 
822 	if (nr_rows != 1)
823 	{
824 		LM_ERR( "update_subs_rlsdb: TOO MANY MATCHES=%d\n", nr_rows);
825 		rls_dbf.free_result(rls_db, result);
826 		return(-1);
827 	}
828 
829 	/* get the results and fill in return data structure */
830 	rows = RES_ROWS(result);
831 	values = ROW_VALUES(rows);
832 
833 	r_pres_uri = (char *)VAL_STRING(&values[pres_uri_col]);
834 	r_remote_cseq = VAL_INT(&values[rcseq_col]);
835 	r_local_cseq = VAL_INT(&values[lcseq_col]);
836 	r_version = VAL_INT(&values[version_col]);
837 	r_record_route = (char *)VAL_STRING(&values[rroute_col]);
838 
839 	if ( r_remote_cseq >= subs->remote_cseq)
840 	{
841 		LM_DBG("stored cseq= %d\n", r_remote_cseq);
842 		rls_dbf.free_result(rls_db, result);
843 		return(401); /*stale cseq code */
844 	}
845 
846 	if(strlen(r_pres_uri) > 0)
847 	{
848 		subs->pres_uri.s =
849 				(char*)pkg_malloc(strlen(r_pres_uri) * sizeof(char));
850 		if(subs->pres_uri.s==NULL)
851 		{
852 			LM_ERR( "Out of Memory\n" );
853 			rls_dbf.free_result(rls_db, result);
854 			return(-1);
855 		}
856 		memcpy(subs->pres_uri.s,
857 			r_pres_uri, strlen(r_pres_uri));
858 		subs->pres_uri.len= strlen(r_pres_uri);
859 	}
860 
861 	if(strlen(r_record_route) > 0)
862 	{
863 		subs->record_route.s =
864 				(char*)pkg_malloc(strlen(r_record_route) * sizeof(char));
865 		if(subs->record_route.s==NULL)
866 		{
867 			LM_ERR( "Out of Memory\n" );
868 			rls_dbf.free_result(rls_db, result);
869 			return(-1);
870 		}
871 		memcpy(subs->record_route.s,
872 			r_record_route, strlen(r_record_route));
873 		subs->record_route.len= strlen(r_record_route);
874 	}
875 
876 	subs->local_cseq= r_local_cseq;
877 	subs->version= r_version;
878 
879 	rls_dbf.free_result(rls_db, result);
880 	return 1;
881 }
882 
883 /******************************************************************************/
884 
get_dialog_notify_rlsdb(str callid,str to_tag,str from_tag)885 subs_t *get_dialog_notify_rlsdb(str callid, str to_tag, str from_tag)
886 {
887 	db_key_t query_cols[4];
888 	db_val_t query_vals[4];
889 	db_key_t result_cols[22];
890 	int n_query_cols = 0, n_result_cols=0;
891 	int r_pres_uri_col,r_to_user_col,r_to_domain_col;
892 	int r_from_user_col,r_from_domain_col,r_callid_col;
893 	int r_to_tag_col,r_from_tag_col,r_socket_info_col;
894 	int r_event_id_col,r_local_contact_col,r_contact_col;
895 	int r_record_route_col, r_reason_col, r_event_col;
896 	int r_local_cseq_col, r_remote_cseq_col, r_status_col;
897 	int r_version_col, r_watcher_user_col, r_watcher_domain_col;
898 	int r_expires_col;
899 	db1_res_t *result= NULL;
900 	db_val_t *values;
901 	db_row_t *rows;
902 	int nr_rows, size;
903 	subs_t *dest;
904 	event_t parsed_event;
905 	str ev_sname;
906 	db_query_f query_fn = rls_dbf.query_lock ? rls_dbf.query_lock : rls_dbf.query;
907 
908 	if(rls_db == NULL)
909 	{
910 		LM_ERR("null database connection\n");
911 		return(NULL);
912 	}
913 
914 	if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
915 	{
916 		LM_ERR("use table failed\n");
917 		return(NULL);
918 	}
919 
920 	query_cols[n_query_cols] = &str_callid_col;
921 	query_vals[n_query_cols].type = DB1_STR;
922 	query_vals[n_query_cols].nul = 0;
923 	query_vals[n_query_cols].val.str_val= callid;
924 	n_query_cols++;
925 
926 	query_cols[n_query_cols] = &str_to_tag_col;
927 	query_vals[n_query_cols].type = DB1_STR;
928 	query_vals[n_query_cols].nul = 0;
929 	query_vals[n_query_cols].val.str_val= to_tag;
930 	n_query_cols++;
931 
932 	query_cols[n_query_cols] = &str_from_tag_col;
933 	query_vals[n_query_cols].type = DB1_STR;
934 	query_vals[n_query_cols].nul = 0;
935 	query_vals[n_query_cols].val.str_val= from_tag;
936 	n_query_cols++;
937 
938 	query_cols[n_query_cols] = &str_updated_col;
939 	query_vals[n_query_cols].type = DB1_INT;
940 	query_vals[n_query_cols].nul = 0;
941 	query_vals[n_query_cols].val.int_val= NO_UPDATE_TYPE;
942 	n_query_cols++;
943 
944 	result_cols[r_pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
945 	result_cols[r_to_user_col=n_result_cols++] = &str_to_user_col;
946 	result_cols[r_to_domain_col=n_result_cols++] = &str_to_domain_col;
947 	result_cols[r_from_user_col=n_result_cols++] = &str_from_user_col;
948 	result_cols[r_from_domain_col=n_result_cols++] = &str_from_domain_col;
949 	result_cols[r_watcher_user_col=n_result_cols++] = &str_watcher_username_col;
950 	result_cols[r_watcher_domain_col=n_result_cols++] = &str_watcher_domain_col;
951 	result_cols[r_callid_col=n_result_cols++] = &str_callid_col;
952 	result_cols[r_to_tag_col=n_result_cols++] = &str_to_tag_col;
953 	result_cols[r_from_tag_col=n_result_cols++] = &str_from_tag_col;
954 	result_cols[r_socket_info_col=n_result_cols++] = &str_socket_info_col;
955 	result_cols[r_event_id_col=n_result_cols++] = &str_event_id_col;
956 	result_cols[r_local_contact_col=n_result_cols++] = &str_local_contact_col;
957 	result_cols[r_contact_col=n_result_cols++] = &str_contact_col;
958 	result_cols[r_record_route_col=n_result_cols++] = &str_record_route_col;
959 	result_cols[r_reason_col=n_result_cols++] = &str_reason_col;
960 	result_cols[r_event_col=n_result_cols++] = &str_event_col;
961 	result_cols[r_local_cseq_col=n_result_cols++] = &str_local_cseq_col;
962 	result_cols[r_remote_cseq_col=n_result_cols++] = &str_remote_cseq_col;
963 	result_cols[r_status_col=n_result_cols++] = &str_status_col;
964 	result_cols[r_version_col=n_result_cols++] = &str_version_col;
965 	result_cols[r_expires_col=n_result_cols++] = &str_expires_col;
966 
967 	if(query_fn(rls_db, query_cols, 0, query_vals, result_cols,
968 				n_query_cols, n_result_cols, 0, &result )< 0)
969 	{
970 		LM_ERR("Can't query db\n");
971 		if(result) rls_dbf.free_result(rls_db, result);
972 		return(NULL);
973 	}
974 
975 	if(result == NULL) return(NULL);
976 
977 	nr_rows = RES_ROW_N(result);
978 
979 	if (nr_rows == 0)
980 	{
981 		/* no match */
982 		LM_INFO( "get_dialog_rlsdb No matching records\n" );
983 		rls_dbf.free_result(rls_db, result);
984 		return(NULL);
985 	}
986 
987 	if (nr_rows != 1)
988 	{
989 		LM_ERR( "get_dialog_rlsdb multiple matching records\n" );
990 		rls_dbf.free_result(rls_db, result);
991 		return(NULL);
992 	}
993 
994 	/* get the results and fill in return data structure */
995 	rows = RES_ROWS(result);
996 	values = ROW_VALUES(rows);
997 
998 	size= sizeof(subs_t) +
999 		( strlen(VAL_STRING(values+r_pres_uri_col))
1000 		+ strlen(VAL_STRING(values+r_to_user_col))
1001 		+ strlen(VAL_STRING(values+r_to_domain_col))
1002 		+ strlen(VAL_STRING(values+r_from_user_col))
1003 		+ strlen(VAL_STRING(values+r_from_domain_col))
1004 		+ strlen(VAL_STRING(values+r_watcher_user_col))
1005 		+ strlen(VAL_STRING(values+r_watcher_domain_col))
1006 		+ strlen(VAL_STRING(values+r_to_tag_col))
1007 		+ strlen(VAL_STRING(values+r_from_tag_col))
1008 		+ strlen(VAL_STRING(values+r_callid_col))
1009 		+ strlen(VAL_STRING(values+r_socket_info_col))
1010 		+ strlen(VAL_STRING(values+r_local_contact_col))
1011 		+ strlen(VAL_STRING(values+r_contact_col))
1012 		+ strlen(VAL_STRING(values+r_record_route_col))
1013 		+ strlen(VAL_STRING(values+r_event_id_col))
1014 		+ strlen(VAL_STRING(values+r_reason_col)))*sizeof(char);
1015 
1016 	dest= (subs_t*)pkg_malloc(size);
1017 
1018 	if(dest== NULL)
1019 	{
1020 		LM_ERR( "Can't allocate memory\n" );
1021 		rls_dbf.free_result(rls_db, result);
1022 		return(NULL);
1023 	}
1024 	memset(dest, 0, size);
1025 	size= sizeof(subs_t);
1026 
1027 	CONT_COPYDB(dest, dest->pres_uri, VAL_STRING(values+r_pres_uri_col));
1028 	CONT_COPYDB(dest, dest->to_user, VAL_STRING(values+r_to_user_col));
1029 	CONT_COPYDB(dest, dest->to_domain, VAL_STRING(values+r_to_domain_col));
1030 	CONT_COPYDB(dest, dest->from_user, VAL_STRING(values+r_from_user_col));
1031 	CONT_COPYDB(dest, dest->from_domain, VAL_STRING(values+r_from_domain_col));
1032 	CONT_COPYDB(dest, dest->watcher_user, VAL_STRING(values+r_watcher_user_col));
1033 	CONT_COPYDB(dest, dest->watcher_domain, VAL_STRING(values+r_watcher_domain_col));
1034 	CONT_COPYDB(dest, dest->to_tag, VAL_STRING(values+r_to_tag_col));
1035 	CONT_COPYDB(dest, dest->from_tag, VAL_STRING(values+r_from_tag_col));
1036 	CONT_COPYDB(dest, dest->callid, VAL_STRING(values+r_callid_col));
1037 	CONT_COPYDB(dest, dest->sockinfo_str, VAL_STRING(values+r_socket_info_col));
1038 	CONT_COPYDB(dest, dest->local_contact, VAL_STRING(values+r_local_contact_col));
1039 	CONT_COPYDB(dest, dest->contact, VAL_STRING(values+r_contact_col));
1040 	CONT_COPYDB(dest, dest->record_route, VAL_STRING(values+r_record_route_col));
1041 
1042 	if(strlen(VAL_STRING(values+r_event_id_col)) > 0)
1043 		CONT_COPYDB(dest, dest->event_id, VAL_STRING(values+r_event_id_col));
1044 
1045 	if(strlen(VAL_STRING(values+r_reason_col)) > 0)
1046 		CONT_COPYDB(dest, dest->reason, VAL_STRING(values+r_reason_col));
1047 
1048 	ev_sname.s= (char *)VAL_STRING(values+r_event_col);
1049 	ev_sname.len= strlen(ev_sname.s);
1050 
1051 	dest->event = pres_contains_event(&ev_sname, &parsed_event);
1052 
1053 	if(dest->event == NULL)
1054 		LM_ERR("event not found and set to NULL\n");
1055 
1056 	dest->local_cseq= VAL_INT(values+r_local_cseq_col);
1057 	dest->remote_cseq= VAL_INT(values+r_remote_cseq_col);
1058 	dest->status= VAL_INT(values+r_status_col);
1059 	dest->version= VAL_INT(values+r_version_col);
1060 	dest->expires= VAL_INT(values+r_expires_col);
1061 
1062 	rls_dbf.free_result(rls_db, result);
1063 
1064 	return(dest);
1065 }
1066 
1067 /******************************************************************************/
1068 
1069