Browse code

dialog: safety checks for bind addr fields

- they can be null on non-local sockets
- GH #2757

Daniel-Constantin Mierla authored on 03/06/2021 13:28:31
Showing 1 changed files
... ...
@@ -802,6 +802,7 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
802 802
 	int i;
803 803
 	struct dlg_var *var;
804 804
 	srjson_doc_t jdoc;
805
+	str sempty = str_init("");
805 806
 
806 807
 	db_val_t values[DIALOG_TABLE_COL_NO];
807 808
 
... ...
@@ -870,14 +871,25 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
870 871
 		SET_STR_VALUE(values+6, cell->tag[DLG_CALLEE_LEG]);
871 872
 		SET_PROPER_NULL_FLAG(cell->tag[DLG_CALLEE_LEG], values, 6);
872 873
 
873
-		LM_DBG("caller sock_info is %.*s, callee sock_info is %.*s\n",
874
-			cell->bind_addr[DLG_CALLER_LEG]->sock_str.len,
875
-			cell->bind_addr[DLG_CALLER_LEG]->sock_str.s,
876
-			cell->bind_addr[DLG_CALLEE_LEG]->sock_str.len,
877
-			cell->bind_addr[DLG_CALLEE_LEG]->sock_str.s);
878 874
 
879
-		SET_STR_VALUE(values+7, cell->bind_addr[DLG_CALLER_LEG]->sock_str);
880
-		SET_STR_VALUE(values+8, cell->bind_addr[DLG_CALLEE_LEG]->sock_str);
875
+		if(cell->bind_addr[DLG_CALLER_LEG]) {
876
+			LM_DBG("caller sock_info is %.*s\n",
877
+				cell->bind_addr[DLG_CALLER_LEG]->sock_str.len,
878
+				cell->bind_addr[DLG_CALLER_LEG]->sock_str.s);
879
+			SET_STR_VALUE(values+7, cell->bind_addr[DLG_CALLER_LEG]->sock_str);
880
+		} else {
881
+			LM_DBG("no caller sock_info\n");
882
+			SET_STR_VALUE(values+7, sempty);
883
+		}
884
+		if(cell->bind_addr[DLG_CALLEE_LEG]) {
885
+			LM_DBG("callee sock_info is %.*s\n",
886
+				cell->bind_addr[DLG_CALLEE_LEG]->sock_str.len,
887
+				cell->bind_addr[DLG_CALLEE_LEG]->sock_str.s);
888
+			SET_STR_VALUE(values+8, cell->bind_addr[DLG_CALLEE_LEG]->sock_str);
889
+		} else {
890
+			LM_DBG("no callee sock_info\n");
891
+			SET_STR_VALUE(values+8, sempty);
892
+		}
881 893
 
882 894
 		SET_STR_VALUE(values+12, cell->cseq[DLG_CALLER_LEG]);
883 895
 		SET_STR_VALUE(values+13, cell->cseq[DLG_CALLEE_LEG]);
Browse code

dialog: fix error in debug logging, properly log both sockets

Henning Westerholt authored on 14/06/2020 15:13:31
Showing 1 changed files
... ...
@@ -870,8 +870,10 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
870 870
 		SET_STR_VALUE(values+6, cell->tag[DLG_CALLEE_LEG]);
871 871
 		SET_PROPER_NULL_FLAG(cell->tag[DLG_CALLEE_LEG], values, 6);
872 872
 
873
-		LM_DBG("sock_info is %.*s\n", 
873
+		LM_DBG("caller sock_info is %.*s, callee sock_info is %.*s\n",
874 874
 			cell->bind_addr[DLG_CALLER_LEG]->sock_str.len,
875
+			cell->bind_addr[DLG_CALLER_LEG]->sock_str.s,
876
+			cell->bind_addr[DLG_CALLEE_LEG]->sock_str.len,
875 877
 			cell->bind_addr[DLG_CALLEE_LEG]->sock_str.s);
876 878
 
877 879
 		SET_STR_VALUE(values+7, cell->bind_addr[DLG_CALLER_LEG]->sock_str);
Browse code

Revert "dialog: add parameter to configure synchronisation of all dialog states to DB"

This reverts commit 37d83a5838a50350563f19387fad455d6a433a02 for now.

It needs more rectoring and some extensions in the DB access layer for this module.

Henning Westerholt authored on 14/06/2020 15:09:25
Showing 1 changed files
... ...
@@ -81,7 +81,6 @@ static db1_con_t* dialog_db_handle    = 0; /* database connection handle */
81 81
 static db_func_t dialog_dbf;
82 82
 
83 83
 extern int dlg_enable_stats;
84
-extern int dlg_update_all_states;
85 84
 extern int dlg_h_id_start;
86 85
 extern int dlg_h_id_step;
87 86
 
... ...
@@ -816,7 +815,7 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
816 815
 			&sflags_column, /*18*/     &toroute_name_column, /*19*/ &req_uri_column, /*20*/
817 816
 			&xdata_column, /*21*/      &iflags_column  /*22*/ };
818 817
 
819
-	if((dlg_update_all_states == 0) && (cell->state<DLG_STATE_EARLY || cell->state==DLG_STATE_DELETED)) {
818
+	if(cell->state<DLG_STATE_EARLY || cell->state==DLG_STATE_DELETED) {
820 819
 		LM_DBG("not storing dlg in db during initial or deleted states\n");
821 820
 		return 0;
822 821
 	}
Browse code

dialog: add parameter to configure synchronisation of all dialog states to DB

- add parameter to configure synchronisation of all dialog states to DB
- new parameter update_all_states added to module interface
- activated by default to provide correct failover behaviour for users
- really large installation should test it and consider the load trade-off

Henning Westerholt authored on 12/06/2020 08:21:20
Showing 1 changed files
... ...
@@ -81,6 +81,7 @@ static db1_con_t* dialog_db_handle    = 0; /* database connection handle */
81 81
 static db_func_t dialog_dbf;
82 82
 
83 83
 extern int dlg_enable_stats;
84
+extern int dlg_update_all_states;
84 85
 extern int dlg_h_id_start;
85 86
 extern int dlg_h_id_step;
86 87
 
... ...
@@ -815,7 +816,7 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
815 816
 			&sflags_column, /*18*/     &toroute_name_column, /*19*/ &req_uri_column, /*20*/
816 817
 			&xdata_column, /*21*/      &iflags_column  /*22*/ };
817 818
 
818
-	if(cell->state<DLG_STATE_EARLY || cell->state==DLG_STATE_DELETED) {
819
+	if((dlg_update_all_states == 0) && (cell->state<DLG_STATE_EARLY || cell->state==DLG_STATE_DELETED)) {
819 820
 		LM_DBG("not storing dlg in db during initial or deleted states\n");
820 821
 		return 0;
821 822
 	}
Browse code

dialog: run DLGCB_LOADED callbacks when loading dialog from db

Federico Cabiddu authored on 13/09/2019 11:56:34
Showing 1 changed files
... ...
@@ -40,6 +40,7 @@
40 40
 #include "../../core/counters.h"
41 41
 #include "dlg_hash.h"
42 42
 #include "dlg_var.h"
43
+#include "dlg_cb.h"
43 44
 #include "dlg_profile.h"
44 45
 #include "dlg_db_handler.h"
45 46
 
... ...
@@ -493,6 +494,7 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
493 494
 					get_ticks());
494 495
 
495 496
 			dlg->dflags = 0;
497
+  
496 498
 			if(mode!=0) {
497 499
 				if(loaded_extra<DLG_MAX_DB_LOAD_EXTRA) {
498 500
 					dbuid[loaded_extra].h_entry = dlg->h_entry;
... ...
@@ -502,6 +504,8 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
502 504
 					dlg->dflags |= DLG_FLAG_DB_LOAD_EXTRA;
503 505
 					loaded_extra_more = 1;
504 506
 				}
507
+			  /* if loading at runtime run the callbacks for the loaded dialog */
508
+			  run_dlg_load_callbacks(dlg);
505 509
 			}
506 510
 			next_dialog:
507 511
 			;
Browse code

dialog: check xdata length when loading profile from db

Federico Cabiddu authored on 08/09/2019 06:58:54
Showing 1 changed files
... ...
@@ -457,7 +457,7 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
457 457
 			dlg_set_toroute(dlg, &toroute_name);
458 458
 
459 459
 			GET_STR_VALUE(xdata, values, 21, 0, 0);
460
-			if(xdata.s!=NULL && dlg->state!=DLG_STATE_DELETED)
460
+			if(xdata.len > 0 && xdata.s!=NULL && dlg->state!=DLG_STATE_DELETED)
461 461
 			{
462 462
 				srjson_InitDoc(&jdoc, NULL);
463 463
 				jdoc.buf = xdata;
Browse code

dialog: convert module to use DB_TABLE_VERSION_ERROR helper

- convert module to use DB_TABLE_VERSION_ERROR helper
- unify error handling (properly close database on errors, null db handle)

Henning Westerholt authored on 30/12/2018 23:44:53
Showing 1 changed files
... ...
@@ -148,34 +148,39 @@ int init_dlg_db(const str *db_url, int dlg_hash_size , int db_update_period, int
148 148
 	}
149 149
 
150 150
 	if(db_check_table_version(&dialog_dbf, dialog_db_handle, &dialog_table_name, DLG_TABLE_VERSION) < 0) {
151
-		LM_ERR("Error during dialog table version check. Please check the database structure.\n");
152
-		return -1;
151
+		DB_TABLE_VERSION_ERROR(dialog_table_name);
152
+		goto dberror;
153 153
 	}
154 154
 
155 155
 	if(db_check_table_version(&dialog_dbf, dialog_db_handle, &dialog_vars_table_name, DLG_VARS_TABLE_VERSION) < 0) {
156
-		LM_ERR("Error during dialog-vars table version check. Please check the database structure\n");
157
-		return -1;
156
+		DB_TABLE_VERSION_ERROR(dialog_vars_table_name);
157
+		goto dberror;
158 158
 	}
159 159
 
160 160
 	if( (dlg_db_mode==DB_MODE_DELAYED) && (register_timer( dialog_update_db, 0, db_update_period)<0 )) {
161 161
 		LM_ERR("Failed to register update db timer\n");
162
-		return -1;
162
+		goto dberror;
163 163
 	}
164 164
 
165 165
 	if ( db_skip_load == 0 ) {
166 166
 		if( (load_dialog_info_from_db(dlg_hash_size, fetch_num_rows, 0, NULL) ) !=0 ){
167 167
 			LM_ERR("Unable to load the dialog data\n");
168
-			return -1;
168
+			goto dberror;
169 169
 		}
170 170
 		if( (load_dialog_vars_from_db(fetch_num_rows, 0, NULL) ) !=0 ){
171 171
 			LM_ERR("Unable to load the dialog variable data\n");
172
-			return -1;
172
+			goto dberror;
173 173
 		}
174 174
 	}
175 175
 	dialog_dbf.close(dialog_db_handle);
176 176
 	dialog_db_handle = 0;
177 177
 
178 178
 	return 0;
179
+
180
+dberror:
181
+	dialog_dbf.close(dialog_db_handle);
182
+	dialog_db_handle = 0;
183
+	return -1;
179 184
 }
180 185
 
181 186
 
Browse code

dialog: fix typo in warn message (#1731)

Thank you!

Dmitri Savolainen authored on 20/11/2018 09:42:05 • Henning Westerholt committed on 20/11/2018 09:42:05
Showing 1 changed files
... ...
@@ -643,14 +643,14 @@ static int load_dialog_vars_from_db(int fetch_num_rows, int mode,
643 643
 					}
644 644
 					dlg = dlg->next;
645 645
 					if (!dlg) {
646
-						LM_WARN("insonsistent data: the dialog h_entry/h_id does not exist!\n");
646
+						LM_WARN("inconsistent data: the dialog h_entry/h_id does not exist!\n");
647 647
 					}
648 648
 				}
649 649
 				if(mode==1 && mval!=NULL) {
650 650
 					dlg_unlock(d_table, &(d_table->entries[VAL_INT(values)]));
651 651
 				}
652 652
 			} else {
653
-				LM_WARN("insonsistent data: the h_entry in the DB does not exist!\n");
653
+				LM_WARN("inconsistent data: the h_entry in the DB does not exist!\n");
654 654
 			}
655 655
 		}
656 656
 
Browse code

dialog: dlg stats incremented twice

Julien Chavanton authored on 15/06/2018 21:50:20 • Henning Westerholt committed on 18/06/2018 21:17:25
Showing 1 changed files
... ...
@@ -80,8 +80,6 @@ static db1_con_t* dialog_db_handle    = 0; /* database connection handle */
80 80
 static db_func_t dialog_dbf;
81 81
 
82 82
 extern int dlg_enable_stats;
83
-extern int active_dlgs_cnt;
84
-extern int early_dlgs_cnt;
85 83
 extern int dlg_h_id_start;
86 84
 extern int dlg_h_id_step;
87 85
 
... ...
@@ -414,10 +412,8 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
414 412
 			dlg->state 		= VAL_INT(values+8);
415 413
 			if (dlg->state==DLG_STATE_CONFIRMED_NA ||
416 414
 			dlg->state==DLG_STATE_CONFIRMED) {
417
-				active_dlgs_cnt++;
418 415
 				if_update_stat(dlg_enable_stats, active_dlgs, 1);
419 416
 			} else if (dlg->state==DLG_STATE_EARLY) {
420
-				early_dlgs_cnt++;
421 417
 				if_update_stat(dlg_enable_stats, early_dlgs, 1);
422 418
 			}
423 419
 
Browse code

dialog: restore keep-alive after restart

Dmitri Savolainen authored on 16/04/2018 16:32:05
Showing 1 changed files
... ...
@@ -464,6 +464,8 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
464 464
 				srjson_DestroyDoc(&jdoc);
465 465
 			}
466 466
 			dlg->iflags = (unsigned int)VAL_INT(values+22);
467
+			if (dlg->state==DLG_STATE_CONFIRMED)
468
+				dlg_ka_add(dlg);
467 469
 
468 470
 			if (!dlg->bind_addr[DLG_CALLER_LEG] || !dlg->bind_addr[DLG_CALLEE_LEG]) {
469 471
 				/* non-local socket, probably not our dialog */
Browse code

dialog: added dlg_db_load_extra() function

- load dialogs from database that are not yet in memory of current
kamailio instance

Daniel-Constantin Mierla authored on 06/04/2018 07:21:02
Showing 1 changed files
... ...
@@ -374,8 +374,13 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
374 374
 					dit = dit->next;
375 375
 				}
376 376
 				if(dit) {
377
-					LM_WARN("conflicting dialog id: %u/%u - skipping\n",
377
+					if(mode==1) {
378
+						LM_WARN("conflicting dialog id: %u/%u - skipping\n",
378 379
 							dlg->h_entry, (unsigned int)VAL_INT(values+1));
380
+					} else {
381
+						LM_DBG("conflicting dialog id: %u/%u - skipping\n",
382
+							dlg->h_entry, (unsigned int)VAL_INT(values+1));
383
+					}
379 384
 					dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
380 385
 					shm_free(dlg);
381 386
 					continue;
... ...
@@ -517,6 +522,23 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
517 522
 		for(i=0; i<loaded_extra; i++) {
518 523
 			load_dialog_vars_from_db(fetch_num_rows, 1, &dbuid[i]);
519 524
 		}
525
+		if(loaded_extra_more) {
526
+			/* more dialogs loaded - scan hash table */
527
+			for(i=0; i<d_table->size; i++) {
528
+				dlg_lock(d_table, &d_table->entries[i]);
529
+				dlg = d_table->entries[i].first;
530
+				while (dlg) {
531
+					if(dlg->dflags & DLG_FLAG_DB_LOAD_EXTRA) {
532
+						dbuid[0].h_entry = dlg->h_entry;
533
+						dbuid[0].h_id = dlg->h_id;
534
+						load_dialog_vars_from_db(fetch_num_rows, 1, &dbuid[0]);
535
+						dlg->dflags &= ~DLG_FLAG_DB_LOAD_EXTRA;
536
+					}
537
+					dlg = dlg->next;
538
+				}
539
+				dlg_unlock(d_table, &d_table->entries[i]);
540
+			}
541
+		}
520 542
 		goto end;
521 543
 	}
522 544
 
Browse code

dialog: added h_id_start and h_id_step parameters

- allow to control how internal dialog hash id is generated to avoid
overalapping values across many instances of kamailio

Daniel-Constantin Mierla authored on 04/04/2018 16:34:55
Showing 1 changed files
... ...
@@ -82,7 +82,8 @@ static db_func_t dialog_dbf;
82 82
 extern int dlg_enable_stats;
83 83
 extern int active_dlgs_cnt;
84 84
 extern int early_dlgs_cnt;
85
-
85
+extern int dlg_h_id_start;
86
+extern int dlg_h_id_step;
86 87
 
87 88
 #define SET_STR_VALUE(_val, _str)\
88 89
 	do{\
... ...
@@ -281,6 +282,7 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
281 282
 	dlg_iuid_t dbuid[DLG_MAX_DB_LOAD_EXTRA];
282 283
 	int loaded_extra = 0;
283 284
 	int loaded_extra_more = 0;
285
+	dlg_cell_t *dit;
284 286
 
285 287
 	if(use_dialog_table() != 0){
286 288
 		return -1;
... ...
@@ -363,6 +365,21 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
363 365
 
364 366
 			if(mode!=0) {
365 367
 				dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
368
+				/* loading at runtime - check dialog id conflicts */
369
+				dit = (d_table->entries)[dlg->h_entry].first;
370
+				while (dit) {
371
+					if (dit->h_id == VAL_INT(values+1)) {
372
+						break;
373
+					}
374
+					dit = dit->next;
375
+				}
376
+				if(dit) {
377
+					LM_WARN("conflicting dialog id: %u/%u - skipping\n",
378
+							dlg->h_entry, (unsigned int)VAL_INT(values+1));
379
+					dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
380
+					shm_free(dlg);
381
+					continue;
382
+				}
366 383
 			}
367 384
 
368 385
 			/*link the dialog*/
... ...
@@ -370,10 +387,17 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
370 387
 
371 388
 			dlg->h_id = VAL_INT(values+1);
372 389
 			next_id = d_table->entries[dlg->h_entry].next_id;
373
-
374
-			d_table->entries[dlg->h_entry].next_id =
375
-				(next_id <= dlg->h_id) ? (dlg->h_id+1) : next_id;
376
-
390
+			if(dlg_h_id_step==1) {
391
+				d_table->entries[dlg->h_entry].next_id =
392
+						(next_id <= dlg->h_id) ? (dlg->h_id+1) : next_id;
393
+			} else {
394
+				/* update next id only if matches this instance series */
395
+				if((dlg->h_id - dlg_h_id_start) % dlg_h_id_step == 0) {
396
+					d_table->entries[dlg->h_entry].next_id =
397
+						(next_id <= dlg->h_id) ? (dlg->h_id + dlg_h_id_step)
398
+								: next_id;
399
+				}
400
+			}
377 401
 			if(mode!=0) {
378 402
 				dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
379 403
 			}
Browse code

dialog: added end labels needed by dlg_db_load_callid()

- they were removed by commit 27c23f57f70936e557d9566e6122958c2e032970
not being used after a previous commit, but meanwhile this function was
developed

Daniel-Constantin Mierla authored on 04/04/2018 06:47:25
Showing 1 changed files
... ...
@@ -503,6 +503,7 @@ int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
503 503
 		}
504 504
 	}
505 505
 
506
+end:
506 507
 	dialog_dbf.free_result(dialog_db_handle, res);
507 508
 	return 0;
508 509
 error:
... ...
@@ -634,6 +635,7 @@ static int load_dialog_vars_from_db(int fetch_num_rows, int mode,
634 635
 		}
635 636
 	}
636 637
 
638
+end:
637 639
 	dialog_dbf.free_result(dialog_db_handle, res);
638 640
 	return 0;
639 641
 error:
Browse code

dialog: added function dlg_db_load_callid(val)

- load dialog from database based on callid parameter
- related to GH #1274

Daniel-Constantin Mierla authored on 04/04/2018 06:35:22
Showing 1 changed files
... ...
@@ -120,9 +120,8 @@ extern int early_dlgs_cnt;
120 120
 		} \
121 121
 	}while(0);
122 122
 
123
-
124
-static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows);
125
-static int load_dialog_vars_from_db(int fetch_num_rows);
123
+static int load_dialog_vars_from_db(int fetch_num_rows, int mode,
124
+		dlg_iuid_t *mval);
126 125
 
127 126
 int dlg_connect_db(const str *db_url)
128 127
 {
... ...
@@ -165,11 +164,11 @@ int init_dlg_db(const str *db_url, int dlg_hash_size , int db_update_period, int
165 164
 	}
166 165
 
167 166
 	if ( db_skip_load == 0 ) {
168
-		if( (load_dialog_info_from_db(dlg_hash_size, fetch_num_rows) ) !=0 ){
167
+		if( (load_dialog_info_from_db(dlg_hash_size, fetch_num_rows, 0, NULL) ) !=0 ){
169 168
 			LM_ERR("Unable to load the dialog data\n");
170 169
 			return -1;
171 170
 		}
172
-		if( (load_dialog_vars_from_db(fetch_num_rows) ) !=0 ){
171
+		if( (load_dialog_vars_from_db(fetch_num_rows, 0, NULL) ) !=0 ){
173 172
 			LM_ERR("Unable to load the dialog variable data\n");
174 173
 			return -1;
175 174
 		}
... ...
@@ -252,7 +251,8 @@ struct socket_info * create_socket_info(db_val_t * vals, int n){
252 251
 
253 252
 
254 253
 
255
-static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
254
+int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows,
255
+		int mode, str *mval)
256 256
 {
257 257
 	db_key_t query_cols[DIALOG_TABLE_COL_NO] = {	&h_entry_column,
258 258
 			&h_id_column,		&call_id_column,	&from_uri_column,
... ...
@@ -263,7 +263,9 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
263 263
 			&from_sock_column,	&to_sock_column,    &sflags_column,
264 264
 			&toroute_name_column,	&req_uri_column, &xdata_column,
265 265
 			&iflags_column};
266
-
266
+	db_key_t match_cols[1] = { &call_id_column };
267
+	db_val_t match_vals[1];
268
+	int match_cols_no = 0;
267 269
 	db1_res_t * res;
268 270
 	db_val_t * values;
269 271
 	db_row_t * rows;
... ...
@@ -275,16 +277,27 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
275 277
 	str xdata;
276 278
 	unsigned int next_id;
277 279
 	srjson_doc_t jdoc;
280
+#define DLG_MAX_DB_LOAD_EXTRA 256
281
+	dlg_iuid_t dbuid[DLG_MAX_DB_LOAD_EXTRA];
282
+	int loaded_extra = 0;
283
+	int loaded_extra_more = 0;
278 284
 
279 285
 	if(use_dialog_table() != 0){
280 286
 		return -1;
281 287
 	}
282 288
 
289
+	if(mode==1 && mval!=NULL && mval->len>0) {
290
+		match_vals[0].type = DB1_STR;
291
+		match_vals[0].nul = 0;
292
+		match_vals[0].val.str_val = *mval;
293
+		match_cols_no = 1;
294
+	}
295
+
283 296
 	res = 0;
284 297
 
285 298
 	if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH) && (fetch_num_rows > 0)) {
286
-		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
287
-				DIALOG_TABLE_COL_NO, 0, 0) < 0) {
299
+		if(dialog_dbf.query(dialog_db_handle, match_cols, 0, match_vals,
300
+				query_cols, match_cols_no, DIALOG_TABLE_COL_NO, 0, 0) < 0) {
288 301
 			LM_ERR("Error while querying (fetch) database\n");
289 302
 			goto error;
290 303
 		}
... ...
@@ -293,8 +306,8 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
293 306
 			goto error;
294 307
 		}
295 308
 	} else {
296
-		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
297
-				DIALOG_TABLE_COL_NO, 0, &res) < 0) {
309
+		if(dialog_dbf.query(dialog_db_handle, match_cols, 0, match_vals,
310
+				query_cols, match_cols_no, DIALOG_TABLE_COL_NO, 0, &res) < 0) {
298 311
 			LM_ERR("Error while querying database\n");
299 312
 			goto error;
300 313
 		}
... ...
@@ -348,6 +361,10 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
348 361
 				goto error;
349 362
 			}
350 363
 
364
+			if(mode!=0) {
365
+				dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
366
+			}
367
+
351 368
 			/*link the dialog*/
352 369
 			link_dlg(dlg, 0, 0);
353 370
 
... ...
@@ -357,6 +374,10 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
357 374
 			d_table->entries[dlg->h_entry].next_id =
358 375
 				(next_id <= dlg->h_id) ? (dlg->h_id+1) : next_id;
359 376
 
377
+			if(mode!=0) {
378
+				dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
379
+			}
380
+
360 381
 			GET_STR_VALUE(to_tag, values, 6, 1, 1);
361 382
 
362 383
 			dlg->start_ts	= VAL_INT(values+7);
... ...
@@ -440,6 +461,16 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
440 461
 					get_ticks());
441 462
 
442 463
 			dlg->dflags = 0;
464
+			if(mode!=0) {
465
+				if(loaded_extra<DLG_MAX_DB_LOAD_EXTRA) {
466
+					dbuid[loaded_extra].h_entry = dlg->h_entry;
467
+					dbuid[loaded_extra].h_id = dlg->h_id;
468
+					loaded_extra++;
469
+				} else {
470
+					dlg->dflags |= DLG_FLAG_DB_LOAD_EXTRA;
471
+					loaded_extra_more = 1;
472
+				}
473
+			}
443 474
 			next_dialog:
444 475
 			;
445 476
 		}
... ...
@@ -458,6 +489,13 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
458 489
 
459 490
 	} while (nr_rows>0);
460 491
 
492
+	if(mode!=0) {
493
+		for(i=0; i<loaded_extra; i++) {
494
+			load_dialog_vars_from_db(fetch_num_rows, 1, &dbuid[i]);
495
+		}
496
+		goto end;
497
+	}
498
+
461 499
 	if (dlg_db_mode==DB_MODE_SHUTDOWN) {
462 500
 		if (dialog_dbf.delete(dialog_db_handle, 0, 0, 0, 0) < 0) {
463 501
 			LM_ERR("failed to clear dialog table\n");
... ...
@@ -473,11 +511,14 @@ error:
473 511
 
474 512
 }
475 513
 
476
-static int load_dialog_vars_from_db(int fetch_num_rows)
514
+static int load_dialog_vars_from_db(int fetch_num_rows, int mode,
515
+		dlg_iuid_t *mval)
477 516
 {
478 517
 	db_key_t query_cols[DIALOG_VARS_TABLE_COL_NO] = {	&vars_h_entry_column,
479 518
 			&vars_h_id_column,	&vars_key_column,	&vars_value_column };
480
-
519
+	db_key_t match_cols[2] = { &vars_h_entry_column, &vars_h_id_column};
520
+	db_val_t match_vals[2];
521
+	int match_cols_no = 0;
481 522
 	db1_res_t * res;
482 523
 	db_val_t * values;
483 524
 	db_row_t * rows;
... ...
@@ -488,11 +529,20 @@ static int load_dialog_vars_from_db(int fetch_num_rows)
488 529
 		return -1;
489 530
 	}
490 531
 
532
+	if(mode==1 && mval!=NULL) {
533
+		VAL_TYPE(match_vals) = VAL_TYPE(match_vals+1) = DB1_INT;
534
+		VAL_NULL(match_vals) = VAL_NULL(match_vals+1) = 0;
535
+		VAL_INT(match_vals) = mval->h_entry;
536
+		VAL_INT(match_vals+1) = mval->h_id;
537
+		match_cols_no = 2;
538
+	}
539
+
491 540
 	res = 0;
492 541
 	/* select the whole table and all the columns */
493 542
 	if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH) && (fetch_num_rows > 0)) {
494
-		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
495
-				DIALOG_VARS_TABLE_COL_NO, 0, 0) < 0) {
543
+		if(dialog_dbf.query(dialog_db_handle, match_cols, 0, match_vals,
544
+				query_cols, match_cols_no, DIALOG_VARS_TABLE_COL_NO, 0, 0)
545
+				< 0) {
496 546
 			LM_ERR("Error while querying (fetch) database\n");
497 547
 			goto error;
498 548
 		}
... ...
@@ -501,8 +551,9 @@ static int load_dialog_vars_from_db(int fetch_num_rows)
501 551
 			goto error;
502 552
 		}
503 553
 	} else {
504
-		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
505
-					DIALOG_VARS_TABLE_COL_NO, 0, &res) < 0) {
554
+		if(dialog_dbf.query(dialog_db_handle, match_cols, 0, match_vals,
555
+					query_cols, match_cols_no, DIALOG_VARS_TABLE_COL_NO, 0,
556
+					&res) < 0) {
506 557
 			LM_ERR("Error while querying database\n");
507 558
 			goto error;
508 559
 		}
... ...
@@ -534,6 +585,9 @@ static int load_dialog_vars_from_db(int fetch_num_rows)
534 585
 				continue;
535 586
 			}
536 587
 			if (VAL_INT(values) < d_table->size) {
588
+				if(mode==1 && mval!=NULL) {
589
+					dlg_lock(d_table, &(d_table->entries[VAL_INT(values)]));
590
+				}
537 591
 				dlg = (d_table->entries)[VAL_INT(values)].first;
538 592
 				while (dlg) {
539 593
 					if (dlg->h_id == VAL_INT(values+1)) {
... ...
@@ -547,6 +601,9 @@ static int load_dialog_vars_from_db(int fetch_num_rows)
547 601
 						LM_WARN("insonsistent data: the dialog h_entry/h_id does not exist!\n");
548 602
 					}
549 603
 				}
604
+				if(mode==1 && mval!=NULL) {
605
+					dlg_unlock(d_table, &(d_table->entries[VAL_INT(values)]));
606
+				}
550 607
 			} else {
551 608
 				LM_WARN("insonsistent data: the h_entry in the DB does not exist!\n");
552 609
 			}
... ...
@@ -566,6 +623,10 @@ static int load_dialog_vars_from_db(int fetch_num_rows)
566 623
 
567 624
 	}while (nr_rows>0);
568 625
 
626
+	if(mode!=0) {
627
+		goto end;
628
+	}
629
+
569 630
 	if (dlg_db_mode==DB_MODE_SHUTDOWN) {
570 631
 		if (dialog_dbf.delete(dialog_db_handle, 0, 0, 0, 0) < 0) {
571 632
 			LM_ERR("failed to clear dialog variable table\n");
Browse code

dialog: fix warning about unused end label, left over from commit 5362d0f78ef

Henning Westerholt authored on 03/04/2018 19:46:18
Showing 1 changed files
... ...
@@ -465,7 +465,6 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
465 465
 		}
466 466
 	}
467 467
 
468
-end:
469 468
 	dialog_dbf.free_result(dialog_db_handle, res);
470 469
 	return 0;
471 470
 error:
... ...
@@ -574,7 +573,6 @@ static int load_dialog_vars_from_db(int fetch_num_rows)
574 573
 		}
575 574
 	}
576 575
 
577
-end:
578 576
 	dialog_dbf.free_result(dialog_db_handle, res);
579 577
 	return 0;
580 578
 error:
Browse code

dialog: merged functions related to loading records from db

- select operation was done in a dedicated function without a good
reason, result being processed in another one

Daniel-Constantin Mierla authored on 02/04/2018 15:57:42
Showing 1 changed files
... ...
@@ -223,48 +223,6 @@ static int use_dialog_vars_table(void)
223 223
 	return 0;
224 224
 }
225 225
 
226
-
227
-
228
-static int select_entire_dialog_table(db1_res_t ** res, int fetch_num_rows)
229
-{
230
-	db_key_t query_cols[DIALOG_TABLE_COL_NO] = {	&h_entry_column,
231
-			&h_id_column,		&call_id_column,	&from_uri_column,
232
-			&from_tag_column,	&to_uri_column,		&to_tag_column,
233
-			&start_time_column,	&state_column,		&timeout_column,
234
-			&from_cseq_column,	&to_cseq_column,	&from_route_column,
235
-			&to_route_column, 	&from_contact_column, &to_contact_column,
236
-			&from_sock_column,	&to_sock_column,    &sflags_column,
237
-			&toroute_name_column,	&req_uri_column, &xdata_column,
238
-			&iflags_column};
239
-
240
-	if(use_dialog_table() != 0){
241
-		return -1;
242
-	}
243
-
244
-	/* select the whole tabel and all the columns */
245
-	if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH) && (fetch_num_rows > 0)) {
246
-		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0, 
247
-		DIALOG_TABLE_COL_NO, 0, 0) < 0) {
248
-			LM_ERR("Error while querying (fetch) database\n");
249
-			return -1;
250
-		}
251
-		if(dialog_dbf.fetch_result(dialog_db_handle, res, fetch_num_rows) < 0) {
252
-			LM_ERR("fetching rows failed\n");
253
-			return -1;
254
-		}
255
-	} else {
256
-		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
257
-		DIALOG_TABLE_COL_NO, 0, res) < 0) {
258
-			LM_ERR("Error while querying database\n");
259
-			return -1;
260
-		}
261
-	}
262
-
263
-	return 0;
264
-}
265
-
266
-
267
-
268 226
 struct socket_info * create_socket_info(db_val_t * vals, int n){
269 227
 
270 228
 	struct socket_info * sock;
... ...
@@ -296,6 +254,16 @@ struct socket_info * create_socket_info(db_val_t * vals, int n){
296 254
 
297 255
 static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
298 256
 {
257
+	db_key_t query_cols[DIALOG_TABLE_COL_NO] = {	&h_entry_column,
258
+			&h_id_column,		&call_id_column,	&from_uri_column,
259
+			&from_tag_column,	&to_uri_column,		&to_tag_column,
260
+			&start_time_column,	&state_column,		&timeout_column,
261
+			&from_cseq_column,	&to_cseq_column,	&from_route_column,
262
+			&to_route_column, 	&from_contact_column, &to_contact_column,
263
+			&from_sock_column,	&to_sock_column,    &sflags_column,
264
+			&toroute_name_column,	&req_uri_column, &xdata_column,
265
+			&iflags_column};
266
+
299 267
 	db1_res_t * res;
300 268
 	db_val_t * values;
301 269
 	db_row_t * rows;
... ...
@@ -307,10 +275,30 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
307 275
 	str xdata;
308 276
 	unsigned int next_id;
309 277
 	srjson_doc_t jdoc;
310
-	
278
+
279
+	if(use_dialog_table() != 0){
280
+		return -1;
281
+	}
282
+
311 283
 	res = 0;
312
-	if((nr_rows = select_entire_dialog_table(&res, fetch_num_rows)) < 0)
313
-		goto end;
284
+
285
+	if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH) && (fetch_num_rows > 0)) {
286
+		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
287
+				DIALOG_TABLE_COL_NO, 0, 0) < 0) {
288
+			LM_ERR("Error while querying (fetch) database\n");
289
+			goto error;
290
+		}
291
+		if(dialog_dbf.fetch_result(dialog_db_handle, &res, fetch_num_rows) < 0) {
292
+			LM_ERR("fetching rows failed\n");
293
+			goto error;
294
+		}
295
+	} else {
296
+		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
297
+				DIALOG_TABLE_COL_NO, 0, &res) < 0) {
298
+			LM_ERR("Error while querying database\n");
299
+			goto error;
300
+		}
301
+	}
314 302
 
315 303
 	nr_rows = RES_ROW_N(res);
316 304
 
... ...
@@ -468,7 +456,7 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
468 456
 			nr_rows = 0;
469 457
 		}
470 458
 
471
-	}while (nr_rows>0);
459
+	} while (nr_rows>0);
472 460
 
473 461
 	if (dlg_db_mode==DB_MODE_SHUTDOWN) {
474 462
 		if (dialog_dbf.delete(dialog_db_handle, 0, 0, 0, 0) < 0) {
... ...
@@ -481,56 +469,46 @@ end:
481 469
 	dialog_dbf.free_result(dialog_db_handle, res);
482 470
 	return 0;
483 471
 error:
484
-	dialog_dbf.free_result(dialog_db_handle, res);
472
+	if(res!=NULL) dialog_dbf.free_result(dialog_db_handle, res);
485 473
 	return -1;
486 474
 
487 475
 }
488 476
 
489
-
490
-
491
-static int select_entire_dialog_vars_table(db1_res_t ** res, int fetch_num_rows)
477
+static int load_dialog_vars_from_db(int fetch_num_rows)
492 478
 {
493 479
 	db_key_t query_cols[DIALOG_VARS_TABLE_COL_NO] = {	&vars_h_entry_column,
494 480
 			&vars_h_id_column,	&vars_key_column,	&vars_value_column };
495 481
 
482
+	db1_res_t * res;
483
+	db_val_t * values;
484
+	db_row_t * rows;
485
+	struct dlg_cell  * dlg;
486
+	int i, nr_rows;
487
+
496 488
 	if(use_dialog_vars_table() != 0){
497 489
 		return -1;
498 490
 	}
499 491
 
500
-	/* select the whole tabel and all the columns */
492
+	res = 0;
493
+	/* select the whole table and all the columns */
501 494
 	if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH) && (fetch_num_rows > 0)) {
502
-		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0, 
503
-		DIALOG_VARS_TABLE_COL_NO, 0, 0) < 0) {
495
+		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
496
+				DIALOG_VARS_TABLE_COL_NO, 0, 0) < 0) {
504 497
 			LM_ERR("Error while querying (fetch) database\n");
505
-			return -1;
498
+			goto error;
506 499
 		}
507
-		if(dialog_dbf.fetch_result(dialog_db_handle, res, fetch_num_rows) < 0) {
500
+		if(dialog_dbf.fetch_result(dialog_db_handle, &res, fetch_num_rows) < 0) {
508 501
 			LM_ERR("fetching rows failed\n");
509
-			return -1;
502
+			goto error;
510 503
 		}
511 504
 	} else {
512 505
 		if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
513
-		DIALOG_VARS_TABLE_COL_NO, 0, res) < 0) {
506
+					DIALOG_VARS_TABLE_COL_NO, 0, &res) < 0) {
514 507
 			LM_ERR("Error while querying database\n");
515
-			return -1;
508
+			goto error;
516 509
 		}
517 510
 	}
518 511
 
519
-	return 0;
520
-}
521
-
522
-static int load_dialog_vars_from_db(int fetch_num_rows)
523
-{
524
-	db1_res_t * res;
525
-	db_val_t * values;
526
-	db_row_t * rows;
527
-	struct dlg_cell  * dlg; 
528
-	int i, nr_rows;
529
-
530
-	res = 0;
531
-	if((nr_rows = select_entire_dialog_vars_table(&res, fetch_num_rows)) < 0)
532
-		goto end;
533
-
534 512
 	nr_rows = RES_ROW_N(res);
535 513
 
536 514
 	LM_DBG("the database has information about %i dialog variables\n", nr_rows);
... ...
@@ -600,7 +578,7 @@ end:
600 578
 	dialog_dbf.free_result(dialog_db_handle, res);
601 579
 	return 0;
602 580
 error:
603
-	dialog_dbf.free_result(dialog_db_handle, res);
581
+	if(res!=0) dialog_dbf.free_result(dialog_db_handle, res);
604 582
 	return -1;
605 583
 
606 584
 }
Browse code

core, lib, modules: updated include paths for header files

Daniel-Constantin Mierla authored on 07/12/2016 11:07:22
Showing 1 changed files
... ...
@@ -31,13 +31,13 @@
31 31
 #include <string.h>
32 32
 #include <sys/time.h>
33 33
 
34
-#include "../../dprint.h"
35
-#include "../../ut.h"
36
-#include "../../timer.h"
34
+#include "../../core/dprint.h"
35
+#include "../../core/ut.h"
36
+#include "../../core/timer.h"
37 37
 #include "../../lib/srdb1/db.h"
38
-#include "../../str.h"
39
-#include "../../socket_info.h"
40
-#include "../../counters.h"
38
+#include "../../core/str.h"
39
+#include "../../core/socket_info.h"
40
+#include "../../core/counters.h"
41 41
 #include "dlg_hash.h"
42 42
 #include "dlg_var.h"
43 43
 #include "dlg_profile.h"
Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,908 @@
1
+/*
2
+ * Copyright (C) 2007 Voice System SRL
3
+ * Copyright (C) 2011 Carsten Bock, carsten@ng-voice.com
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * Kamailio is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * Kamailio is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
+ *
21
+ */
22
+
23
+/*!
24
+ * \file
25
+ * \brief Database interface
26
+ * \ingroup dialog
27
+ * Module: \ref dialog
28
+ */
29
+
30
+#include <stdlib.h>
31
+#include <string.h>
32
+#include <sys/time.h>
33
+
34
+#include "../../dprint.h"
35
+#include "../../ut.h"
36
+#include "../../timer.h"
37
+#include "../../lib/srdb1/db.h"
38
+#include "../../str.h"
39
+#include "../../socket_info.h"
40
+#include "../../counters.h"
41
+#include "dlg_hash.h"
42
+#include "dlg_var.h"
43
+#include "dlg_profile.h"
44
+#include "dlg_db_handler.h"
45
+
46
+
47
+str call_id_column			=	str_init(CALL_ID_COL);
48
+str from_uri_column			=	str_init(FROM_URI_COL);
49
+str from_tag_column			=	str_init(FROM_TAG_COL);
50
+str to_uri_column			=	str_init(TO_URI_COL);
51
+str to_tag_column			=	str_init(TO_TAG_COL);
52
+str h_id_column				=	str_init(HASH_ID_COL);
53
+str h_entry_column			=	str_init(HASH_ENTRY_COL);
54
+str state_column			=	str_init(STATE_COL);
55
+str start_time_column		=	str_init(START_TIME_COL);
56
+str timeout_column			=	str_init(TIMEOUT_COL);
57
+str to_cseq_column			=	str_init(TO_CSEQ_COL);
58
+str from_cseq_column		=	str_init(FROM_CSEQ_COL);
59
+str to_route_column			=	str_init(TO_ROUTE_COL);
60
+str from_route_column		=	str_init(FROM_ROUTE_COL);
61
+str to_contact_column		=	str_init(TO_CONTACT_COL);
62
+str from_contact_column		=	str_init(FROM_CONTACT_COL);
63
+str to_sock_column			=	str_init(TO_SOCK_COL);
64
+str from_sock_column		=	str_init(FROM_SOCK_COL);
65
+str sflags_column			=	str_init(SFLAGS_COL);
66
+str iflags_column			=	str_init(IFLAGS_COL);
67
+str toroute_name_column		=	str_init(TOROUTE_NAME_COL);
68
+str req_uri_column			=	str_init(REQ_URI_COL);
69
+str xdata_column			=	str_init(XDATA_COL);
70
+str dialog_table_name		=	str_init(DIALOG_TABLE_NAME);
71
+int dlg_db_mode				=	DB_MODE_NONE;
72
+
73
+str vars_h_id_column		=	str_init(VARS_HASH_ID_COL);
74
+str vars_h_entry_column		=	str_init(VARS_HASH_ENTRY_COL);
75
+str vars_key_column		=	str_init(VARS_KEY_COL);
76
+str vars_value_column		=	str_init(VARS_VALUE_COL);
77
+str dialog_vars_table_name	=	str_init(DIALOG_VARS_TABLE_NAME);
78
+
79
+static db1_con_t* dialog_db_handle    = 0; /* database connection handle */
80
+static db_func_t dialog_dbf;
81
+
82
+extern int dlg_enable_stats;
83
+extern int active_dlgs_cnt;
84
+extern int early_dlgs_cnt;
85
+
86
+
87
+#define SET_STR_VALUE(_val, _str)\
88
+	do{\
89
+			VAL_STR((_val)).s 		= (_str).s;\
90
+			VAL_STR((_val)).len 	= (_str).len;\
91
+	}while(0);
92
+
93
+#define SET_NULL_FLAG(_vals, _i, _max, _flag)\
94
+	do{\
95
+		for((_i) = 0;(_i)<(_max); (_i)++)\
96
+			VAL_NULL((_vals)+(_i)) = (_flag);\
97
+	}while(0);
98
+
99
+#define SET_PROPER_NULL_FLAG(_str, _vals, _index)\
100
+	do{\
101
+		if( (_str).len == 0)\
102
+			VAL_NULL( (_vals)+(_index) ) = 1;\
103
+		else\
104
+			VAL_NULL( (_vals)+(_index) ) = 0;\
105
+	}while(0);
106
+
107
+#define GET_STR_VALUE(_res, _values, _index, _not_null, _unref)\
108
+	do{\
109
+		if (VAL_NULL((_values)+ (_index))) { \
110
+			if (_not_null) {\
111
+				if (_unref) dlg_unref(dlg,1);\
112
+				goto next_dialog; \