Browse code

dialog(k): more dialog info stored in db

- profiles the dialog belongs to are stored in xdata column, serialized
as json document. A restart will restore them
- internal flags are stored and restored from database table, column
iflags (for now the flag for sending BYE on dialog timeout)

Daniel-Constantin Mierla authored on 17/02/2012 08:26:19
Showing 7 changed files
... ...
@@ -13,4 +13,5 @@ SERLIBPATH=../../lib
13 13
 SER_LIBS+=$(SERLIBPATH)/kmi/kmi
14 14
 SER_LIBS+=$(SERLIBPATH)/srdb1/srdb1
15 15
 SER_LIBS+=$(SERLIBPATH)/kcore/kcore
16
+SER_LIBS+=$(SERLIBPATH)/srutils/srutils
16 17
 include ../../Makefile.modules
... ...
@@ -39,6 +39,7 @@
39 39
 #include "../../socket_info.h"
40 40
 #include "dlg_hash.h"
41 41
 #include "dlg_var.h"
42
+#include "dlg_profile.h"
42 43
 #include "dlg_db_handler.h"
43 44
 
44 45
 
... ...
@@ -61,8 +62,10 @@ str from_contact_column		=	str_init(FROM_CONTACT_COL);
61 61
 str to_sock_column			=	str_init(TO_SOCK_COL);
62 62
 str from_sock_column		=	str_init(FROM_SOCK_COL);
63 63
 str sflags_column			=	str_init(SFLAGS_COL);
64
+str iflags_column			=	str_init(IFLAGS_COL);
64 65
 str toroute_name_column		=	str_init(TOROUTE_NAME_COL);
65 66
 str req_uri_column			=	str_init(REQ_URI_COL);
67
+str xdata_column			=	str_init(XDATA_COL);
66 68
 str dialog_table_name		=	str_init(DIALOG_TABLE_NAME);
67 69
 int dlg_db_mode				=	DB_MODE_NONE;
68 70
 
... ...
@@ -79,6 +82,7 @@ extern int dlg_enable_stats;
79 79
 extern int active_dlgs_cnt;
80 80
 extern int early_dlgs_cnt;
81 81
 
82
+
82 83
 #define SET_STR_VALUE(_val, _str)\
83 84
 	do{\
84 85
 			VAL_STR((_val)).s 		= (_str).s;\
... ...
@@ -229,7 +233,8 @@ static int select_entire_dialog_table(db1_res_t ** res, int fetch_num_rows)
229 229
 			&from_cseq_column,	&to_cseq_column,	&from_route_column,
230 230
 			&to_route_column, 	&from_contact_column, &to_contact_column,
231 231
 			&from_sock_column,	&to_sock_column,    &sflags_column,
232
-			&toroute_name_column,	&req_uri_column };
232
+			&toroute_name_column,	&req_uri_column, &xdata_column,
233
+			&iflags_column};
233 234
 
234 235
 	if(use_dialog_table() != 0){
235 236
 		return -1;
... ...
@@ -298,9 +303,10 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
298 298
 	str callid, from_uri, to_uri, from_tag, to_tag, req_uri;
299 299
 	str cseq1, cseq2, contact1, contact2, rroute1, rroute2;
300 300
 	str toroute_name;
301
+	str xdata;
301 302
 	unsigned int next_id;
303
+	srjson_doc_t jdoc;
302 304
 	
303
-
304 305
 	res = 0;
305 306
 	if((nr_rows = select_entire_dialog_table(&res, fetch_num_rows)) < 0)
306 307
 		goto end;
... ...
@@ -374,11 +380,14 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
374 374
 				early_dlgs_cnt++;
375 375
 			}
376 376
 
377
-			dlg->tl.timeout = (unsigned int)(VAL_INT(values+9)) + get_ticks();
377
+			dlg->tl.timeout = (unsigned int)(VAL_INT(values+9));
378
+			LM_DBG("db dialog timeout is %u (%u/%u)\n", dlg->tl.timeout,
379
+					get_ticks(), (unsigned int)time(0));
378 380
 			if (dlg->tl.timeout<=(unsigned int)time(0))
379 381
 				dlg->tl.timeout = 0;
380 382
 			else
381 383
 				dlg->tl.timeout -= (unsigned int)time(0);
384
+			dlg->lifetime = dlg->tl.timeout;
382 385
 
383 386
 			GET_STR_VALUE(cseq1, values, 10 , 1, 1);
384 387
 			GET_STR_VALUE(cseq2, values, 11 , 1, 1);
... ...
@@ -398,10 +407,21 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
398 398
 
399 399
 			dlg->bind_addr[DLG_CALLER_LEG] = create_socket_info(values, 16);
400 400
 			dlg->bind_addr[DLG_CALLEE_LEG] = create_socket_info(values, 17);
401
-			
401
+
402
+			dlg->sflags = (unsigned int)VAL_INT(values+18);
403
+
402 404
 			GET_STR_VALUE(toroute_name, values, 19, 0, 0);
403 405
 			dlg_set_toroute(dlg, &toroute_name);
404 406
 
407
+			GET_STR_VALUE(xdata, values, 21, 0, 0);
408
+			if(xdata.s!=NULL)
409
+			{
410
+				srjson_InitDoc(&jdoc, NULL);
411
+				jdoc.buf = xdata;
412
+				dlg_json_to_profiles(dlg, &jdoc);
413
+				srjson_DestroyDoc(&jdoc);
414
+			}
415
+			dlg->iflags = (unsigned int)VAL_INT(values+22);
405 416
 			/*restore the timer values */
406 417
 			if (0 != insert_dlg_timer( &(dlg->tl), (int)dlg->tl.timeout )) {
407 418
 				LM_CRIT("Unable to insert dlg %p [%u:%u] "
... ...
@@ -414,9 +434,9 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
414 414
 				continue;
415 415
 			}
416 416
 			dlg_ref(dlg,1);
417
-			LM_DBG("current dialog timeout is %u\n", dlg->tl.timeout);
417
+			LM_DBG("current dialog timeout is %u (%u)\n", dlg->tl.timeout,
418
+					get_ticks());
418 419
 
419
-			dlg->lifetime = 0;
420 420
 			dlg->dflags = 0;
421 421
 			next_dialog:
422 422
 			;
... ...
@@ -675,6 +695,7 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
675 675
 {
676 676
 	int i;
677 677
 	struct dlg_var *var;
678
+	srjson_doc_t jdoc;
678 679
 
679 680
 	db_val_t values[DIALOG_TABLE_COL_NO];
680 681
 
... ...
@@ -685,7 +706,8 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
685 685
 			&start_time_column,  &state_column,       &timeout_column,
686 686
 			&from_cseq_column,   &to_cseq_column,     &from_route_column,
687 687
 			&to_route_column,    &from_contact_column,&to_contact_column,
688
-			&sflags_column,      &toroute_name_column,     &req_uri_column };
688
+			&sflags_column,      &toroute_name_column,     &req_uri_column,
689
+			&xdata_column, &iflags_column };
689 690
 
690 691
 	if( (cell->dflags & DLG_FLAG_NEW) != 0 
691 692
 	|| (cell->dflags & DLG_FLAG_CHANGED_VARS) != 0) {
... ...
@@ -701,6 +723,8 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
701 701
 	if(use_dialog_table()!=0)
702 702
 		return -1;
703 703
 	
704
+	srjson_InitDoc(&jdoc, NULL);
705
+
704 706
 	if((cell->dflags & DLG_FLAG_NEW) != 0){
705 707
 		/* save all the current dialogs information*/
706 708
 		VAL_TYPE(values) = VAL_TYPE(values+1) = VAL_TYPE(values+9) = 
... ...
@@ -715,6 +739,8 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
715 715
 		SET_NULL_FLAG(values, i, DIALOG_TABLE_COL_NO-6, 0);
716 716
 		VAL_TYPE(values+18) = DB1_INT;
717 717
 		VAL_TYPE(values+19) = DB1_STR;
718
+		VAL_TYPE(values+21) = DB1_STR;
719
+		VAL_TYPE(values+22) = DB1_INT;
718 720
 
719 721
 		VAL_INT(values)			= cell->h_entry;
720 722
 		VAL_INT(values+1)		= cell->h_id;
... ...
@@ -757,6 +783,18 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
757 757
 		SET_STR_VALUE(values+20, cell->req_uri);
758 758
 		SET_PROPER_NULL_FLAG(cell->req_uri, 	values, 20);
759 759
 
760
+		dlg_profiles_to_json(cell, &jdoc);
761
+		if(jdoc.buf.s!=NULL)
762
+		{
763
+			SET_STR_VALUE(values+21, jdoc.buf);
764
+			SET_PROPER_NULL_FLAG(jdoc.buf, values, 21);
765
+		} else {
766
+			VAL_NULL(values+21) = 1;
767
+		}
768
+
769
+		VAL_NULL(values+22) = 0;
770
+		VAL_INT(values+22)  = cell->iflags;
771
+
760 772
 		if((dialog_dbf.insert(dialog_db_handle, insert_keys, values, 
761 773
 								DIALOG_TABLE_COL_NO)) !=0){
762 774
 			LM_ERR("could not add another dialog to db\n");
... ...
@@ -795,8 +833,20 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
795 795
 		return 0;
796 796
 	}
797 797
 
798
+	if(jdoc.buf.s!=NULL) {
799
+		jdoc.free_fn(jdoc.buf.s);
800
+		jdoc.buf.s = NULL;
801
+	}
802
+	srjson_DestroyDoc(&jdoc);
803
+
798 804
 	return 0;
805
+
799 806
 error:
807
+	if(jdoc.buf.s!=NULL) {
808
+		jdoc.free_fn(jdoc.buf.s);
809
+		jdoc.buf.s = NULL;
810
+	}
811
+	srjson_DestroyDoc(&jdoc);
800 812
 	return -1;
801 813
 }
802 814
 
... ...
@@ -842,4 +892,3 @@ void dialog_update_db(unsigned int ticks, void * param)
842 842
 error:
843 843
 	dlg_unlock( d_table, &entry);
844 844
 }
845
-
... ...
@@ -50,13 +50,15 @@
50 50
 #define FROM_CONTACT_COL		"caller_contact"
51 51
 #define FROM_SOCK_COL			"caller_sock"
52 52
 #define TO_SOCK_COL				"callee_sock"
53
+#define IFLAGS_COL				"iflags"
53 54
 #define SFLAGS_COL				"sflags"
54 55
 #define TOROUTE_NAME_COL		"toroute_name"
55 56
 #define REQ_URI_COL				"req_uri"
57
+#define XDATA_COL				"xdata"
56 58
 #define DIALOG_TABLE_NAME		"dialog"
57
-#define DLG_TABLE_VERSION		5
59
+#define DLG_TABLE_VERSION		6
58 60
 
59
-#define DIALOG_TABLE_COL_NO 		21
61
+#define DIALOG_TABLE_COL_NO 		23
60 62
 
61 63
 #define VARS_HASH_ID_COL 		"hash_id"
62 64
 #define VARS_HASH_ENTRY_COL		"hash_entry"
... ...
@@ -95,6 +97,7 @@ extern str to_contact_column;
95 95
 extern str from_contact_column;
96 96
 extern str to_sock_column;
97 97
 extern str from_sock_column;
98
+extern str iflags_column;
98 99
 extern str sflags_column;
99 100
 extern str toroute_name_column;
100 101
 extern str dialog_table_name;
... ...
@@ -852,7 +852,7 @@ int dlg_new_dialog(struct sip_msg *req, struct cell *t, const int run_initial_cb
852 852
 	dlg->sflags |= _dlg_ctx.flags;
853 853
 
854 854
 	if (dlg_send_bye!=0 || _dlg_ctx.to_bye!=0)
855
-		dlg->dflags |= DLG_FLAG_TOBYE;
855
+		dlg->iflags |= DLG_IFLAG_TIMEOUTBYE;
856 856
 
857 857
     if (run_initial_cbs)  run_create_callbacks( dlg, req);
858 858
 
... ...
@@ -1332,7 +1332,7 @@ void dlg_ontimeout(struct dlg_tl *tl)
1332 1332
 			}
1333 1333
 		}
1334 1334
 
1335
-		if(dlg->dflags&DLG_FLAG_TOBYE)
1335
+		if(dlg->iflags&DLG_IFLAG_TIMEOUTBYE)
1336 1336
 		{
1337 1337
 			dlg_bye_all(dlg, NULL);
1338 1338
 			/* run event route for end of dlg */
... ...
@@ -66,11 +66,10 @@
66 66
 #define DLG_EVENT_REQBYE       7 /*!< BYE request */
67 67
 #define DLG_EVENT_REQ          8 /*!< other requests */
68 68
 
69
-/* dialog flags */
69
+/* dialog internal flags only in memory */
70 70
 #define DLG_FLAG_NEW           (1<<0) /*!< new dialog */
71 71
 #define DLG_FLAG_CHANGED       (1<<1) /*!< dialog was changed */
72 72
 #define DLG_FLAG_HASBYE        (1<<2) /*!< bye was received */
73
-#define DLG_FLAG_TOBYE         (1<<3) /*!< flag from dialog context */
74 73
 #define DLG_FLAG_CALLERBYE     (1<<4) /*!< bye from caller */
75 74
 #define DLG_FLAG_CALLEEBYE     (1<<5) /*!< bye from callee */
76 75
 #define DLG_FLAG_LOCALDLG      (1<<6) /*!< local dialog, unused */
... ...
@@ -81,6 +80,9 @@
81 81
 
82 82
 #define DLG_FLAG_TM            (1<<9) /*!< dialog is set in transaction */
83 83
 
84
+/* internal flags stored in db */
85
+#define DLG_IFLAG_TIMEOUTBYE        (1<<0) /*!< send bye on time-out */
86
+
84 87
 #define DLG_CALLER_LEG         0 /*!< attribute that belongs to a caller leg */
85 88
 #define DLG_CALLEE_LEG         1 /*!< attribute that belongs to a callee leg */
86 89
 
... ...
@@ -110,8 +112,9 @@ typedef struct dlg_cell
110 110
 	unsigned int         state;		/*!< dialog state */
111 111
 	unsigned int         lifetime;		/*!< dialog lifetime */
112 112
 	unsigned int         start_ts;		/*!< start time  (absolute UNIX ts)*/
113
-	unsigned int         dflags;		/*!< internal dialog flags */
114
-	unsigned int         sflags;		/*!< script dialog flags */
113
+	unsigned int         dflags;		/*!< internal dialog memory flags */
114
+	unsigned int         iflags;		/*!< internal dialog persistent flags */
115
+	unsigned int         sflags;		/*!< script dialog persistent flags */
115 116
 	unsigned int         toroute;		/*!< index of route that is executed on timeout */
116 117
 	str                  toroute_name;	/*!< name of route that is executed on timeout */
117 118
 	unsigned int         from_rr_nb;	/*!< information from record routing */
... ...
@@ -403,6 +403,7 @@ void set_current_dialog(sip_msg_t *msg, dlg_cell_t *dlg)
403 403
 	struct dlg_profile_link *linker;
404 404
 	struct dlg_profile_link *tlinker;
405 405
 
406
+	LM_DBG("setting current dialog [%u:%u]\n", dlg->h_entry, dlg->h_id);
406 407
 	/* if linkers are not from current request, just discard them */
407 408
 	if (msg->id!=current_dlg_msg_id || msg->pid!=current_dlg_msg_pid) {
408 409
 		current_dlg_msg_id = msg->id;
... ...
@@ -468,6 +469,12 @@ int set_dlg_profile(struct sip_msg *msg, str *value, struct dlg_profile_table *p
468 468
 		link_dlg_profile( linker, dlg);
469 469
 	} else {
470 470
 		/* no dialog yet -> set linker as pending */
471
+		if (msg->id!=current_dlg_msg_id || msg->pid!=current_dlg_msg_pid) {
472
+			current_dlg_msg_id = msg->id;
473
+			current_dlg_msg_pid = msg->pid;
474
+			destroy_linkers(current_pending_linkers);
475
+		}
476
+
471 477
 		linker->next = current_pending_linkers;
472 478
 		current_pending_linkers = linker;
473 479
 	}
... ...
@@ -479,6 +486,45 @@ error:
479 479
 	return -1;
480 480
 }
481 481
 
482
+/*!
483
+ * \brief Add dialog to a profile
484
+ * \param dlg dialog
485
+ * \param value value
486
+ * \param profile dialog profile table
487
+ * \return 0 on success, -1 on failure
488
+ */
489
+int dlg_add_profile(dlg_cell_t *dlg, str *value, struct dlg_profile_table *profile)
490
+{
491
+	dlg_profile_link_t *linker;
492
+
493
+	if (dlg==NULL)
494
+		return -1;
495
+
496
+	/* build new linker */
497
+	linker = (struct dlg_profile_link*)shm_malloc(
498
+		sizeof(struct dlg_profile_link) + (profile->has_value?value->len:0) );
499
+	if (linker==NULL) {
500
+		LM_ERR("no more shm memory\n");
501
+		goto error;
502
+	}
503
+	memset(linker, 0, sizeof(struct dlg_profile_link));
504
+
505
+	/* set backpointer to profile */
506
+	linker->profile = profile;
507
+
508
+	/* set the value */
509
+	if (profile->has_value) {
510
+		linker->hash_linker.value.s = (char*)(linker+1);
511
+		memcpy( linker->hash_linker.value.s, value->s, value->len);
512
+		linker->hash_linker.value.len = value->len;
513
+	}
514
+
515
+	/* add linker directly to the dialog and profile */
516
+	link_dlg_profile( linker, dlg);
517
+	return 0;
518
+error:
519
+	return -1;
520
+}
482 521
 
483 522
 /*!
484 523
  * \brief Unset a dialog profile
... ...
@@ -820,3 +866,159 @@ error:
820 820
 	free_mi_tree(rpl_tree);
821 821
 	return NULL;
822 822
 }
823
+
824
+
825
+/**
826
+ * json serialization of dialog profiles
827
+ */
828
+int dlg_profiles_to_json(dlg_cell_t *dlg, srjson_doc_t *jdoc)
829
+{
830
+	dlg_profile_link_t *l;
831
+	srjson_t *sj = NULL;
832
+	srjson_t *dj = NULL;
833
+
834
+	LM_DBG("serializing profiles for dlg[%u:%u]\n",
835
+				dlg->h_entry, dlg->h_id);
836
+	if(dlg==NULL || dlg->profile_links==NULL)
837
+		return -1;
838
+	LM_DBG("start of serializing profiles for dlg[%u:%u]\n",
839
+				dlg->h_entry, dlg->h_id);
840
+
841
+	for (l = dlg->profile_links ; l ; l=l->next) {
842
+		if(l->profile->has_value)
843
+		{
844
+			if(dj==NULL)
845
+			{
846
+				dj = srjson_CreateObject(jdoc);
847
+				if(dj==NULL)
848
+				{
849
+					LM_ERR("cannot create json dynamic profiles obj\n");
850
+					goto error;
851
+				}
852
+			}
853
+			srjson_AddStrStrToObject(jdoc, dj,
854
+					l->profile->name.s, l->profile->name.len,
855
+					l->hash_linker.value.s, l->hash_linker.value.len);
856
+		} else {
857
+			if(sj==NULL)
858
+			{
859
+				sj = srjson_CreateArray(jdoc);
860
+				if(sj==NULL)
861
+				{
862
+					LM_ERR("cannot create json static profiles obj\n");
863
+					goto error;
864
+				}
865
+			}
866
+			srjson_AddItemToArray(jdoc, sj,
867
+					srjson_CreateStr(jdoc, l->profile->name.s, l->profile->name.len));
868
+		}
869
+	}
870
+
871
+	if(jdoc->root==NULL)
872
+	{
873
+		jdoc->root = srjson_CreateObject(jdoc);
874
+		if(jdoc->root==NULL)
875
+		{
876
+			LM_ERR("cannot create json root\n");
877
+			goto error;
878
+		}
879
+	}
880
+	if(dj!=NULL)
881
+		srjson_AddItemToObject(jdoc, jdoc->root, "dprofiles", dj);
882
+	if(sj!=NULL)
883
+		srjson_AddItemToObject(jdoc, jdoc->root, "sprofiles", sj);
884
+	if(jdoc->buf.s != NULL)
885
+	{
886
+		jdoc->free_fn(jdoc->buf.s);
887
+		jdoc->buf.s = NULL;
888
+		jdoc->buf.len = 0;
889
+	}
890
+	jdoc->buf.s = srjson_PrintUnformatted(jdoc, jdoc->root);
891
+	if(jdoc->buf.s!=NULL)
892
+	{
893
+		jdoc->buf.len = strlen(jdoc->buf.s);
894
+		LM_DBG("serialized profiles for dlg[%u:%u] = [[%.*s]]\n",
895
+				dlg->h_entry, dlg->h_id, jdoc->buf.len, jdoc->buf.s);
896
+		return 0;
897
+	}
898
+	return -1;
899
+
900
+error:
901
+	srjson_Delete(jdoc, dj);
902
+	srjson_Delete(jdoc, sj);
903
+	return -1;
904
+}
905
+
906
+
907
+/**
908
+ * json de-serialization of dialog profiles
909
+ */
910
+int dlg_json_to_profiles(dlg_cell_t *dlg, srjson_doc_t *jdoc)
911
+{
912
+	srjson_t *sj = NULL;
913
+	srjson_t *dj = NULL;
914
+	srjson_t *it = NULL;
915
+	dlg_profile_table_t *profile;
916
+	str name;
917
+	str val;
918
+
919
+	if(dlg==NULL || jdoc==NULL || jdoc->buf.s==NULL)
920
+		return -1;
921
+
922
+	if(jdoc->root == NULL)
923
+	{
924
+		jdoc->root = srjson_Parse(jdoc, jdoc->buf.s);
925
+		if(jdoc->root == NULL)
926
+		{
927
+			LM_ERR("invalid json doc [[%s]]\n", jdoc->buf.s);
928
+			return -1;
929
+		}
930
+	}
931
+	dj = srjson_GetObjectItem(jdoc, jdoc->root, "dprofiles");
932
+	sj = srjson_GetObjectItem(jdoc, jdoc->root, "sprofiles");
933
+	if(dj!=NULL)
934
+	{
935
+		for(it=dj->child; it; it = it->next)
936
+		{
937
+			name.s = it->string;
938
+			name.len = strlen(name.s);
939
+			val.s = it->valuestring;
940
+			val.len = strlen(val.s);
941
+			profile = search_dlg_profile(&name);
942
+			if(profile==NULL)
943
+			{
944
+				LM_ERR("profile [%.*s] not found\n", name.len, name.s);
945
+				continue;
946
+			}
947
+			if(profile->has_value)
948
+			{
949
+				if(dlg_add_profile(dlg, &val, profile) < 0)
950
+					LM_ERR("dynamic profile cannot be added, ignore!\n");
951
+				else
952
+					LM_DBG("dynamic profile added [%s : %s]\n", name.s, val.s);
953
+			}
954
+		}
955
+	}
956
+	if(sj!=NULL)
957
+	{
958
+		for(it=sj->child; it; it = it->next)
959
+		{
960
+			name.s = it->valuestring;
961
+			name.len = strlen(name.s);
962
+			profile = search_dlg_profile(&name);
963
+			if(profile==NULL)
964
+			{
965
+				LM_ERR("profile [%.*s] not found\n", name.len, name.s);
966
+				continue;
967
+			}
968
+			if(!profile->has_value)
969
+			{
970
+				if(dlg_add_profile(dlg, NULL, profile) < 0)
971
+					LM_ERR("static profile cannot be added, ignore!\n");
972
+				else
973
+					LM_DBG("static profile added [%s]\n", name.s);
974
+			}
975
+		}
976
+	}
977
+	return 0;
978
+}
... ...
@@ -29,6 +29,7 @@
29 29
 #define _DIALOG_DLG_PROFILE_H_
30 30
 
31 31
 #include "../../parser/msg_parser.h"
32
+#include "../../lib/srutils/srjson.h"
32 33
 #include "../../locking.h"
33 34
 #include "../../str.h"
34 35
 #include "../../modules/tm/h_table.h"
... ...
@@ -193,4 +194,23 @@ struct mi_root * mi_profile_list(struct mi_root *cmd_tree, void *param );
193 193
  */
194 194
 int is_known_dlg(sip_msg_t *msg);
195 195
 
196
+/*!
197
+ * \brief Add dialog to a profile
198
+ * \param dlg dialog
199
+ * \param value value
200
+ * \param profile dialog profile table
201
+ * \return 0 on success, -1 on failure
202
+ */
203
+int dlg_add_profile(dlg_cell_t *dlg, str *value, struct dlg_profile_table *profile);
204
+
205
+/*!
206
+ * \brief Serialize dialog profiles to json
207
+ */
208
+int dlg_profiles_to_json(dlg_cell_t *dlg, srjson_doc_t *jdoc);
209
+
210
+/*!
211
+ * \brief Deserialize dialog profiles to json
212
+ */
213
+int dlg_json_to_profiles(dlg_cell_t *dlg, srjson_doc_t *jdoc);
214
+
196 215
 #endif