From: Victor Seva <linuxmaniac@torreviejawireless.org>
Date: Thu, 28 Oct 2021 11:21:58 +0200
Subject: pua_dialoginfo: generate uuid as id instead of use callid value

This change solves the issue of parallel forking, subscriber
was receiving NOTIFY messages with the same id for different branches

fixes #2906
---
 src/modules/pua_dialoginfo/dialog_publish.c | 18 ++++----
 src/modules/pua_dialoginfo/pua_dialoginfo.c | 71 +++++++++++++++++++++--------
 src/modules/pua_dialoginfo/pua_dialoginfo.h |  3 +-
 3 files changed, 63 insertions(+), 29 deletions(-)

diff --git a/src/modules/pua_dialoginfo/dialog_publish.c b/src/modules/pua_dialoginfo/dialog_publish.c
index 7eaf27b..137823c 100644
--- a/src/modules/pua_dialoginfo/dialog_publish.c
+++ b/src/modules/pua_dialoginfo/dialog_publish.c
@@ -87,7 +87,7 @@ static xmlAttrPtr puadi_xmlNewPropStr(xmlNodePtr node, char *name, str *sval)
 
 str* build_dialoginfo(char *state, str *entity, str *peer, str *callid,
 		unsigned int initiator, str *localtag, str *remotetag,
-		str *localtarget, str *remotetarget)
+		str *localtarget, str *remotetarget, str *uuid)
 {
 	xmlDocPtr  doc = NULL;
 	xmlNodePtr root_node = NULL;
@@ -141,7 +141,7 @@ str* build_dialoginfo(char *state, str *entity, str *peer, str *callid,
 		goto error;
 	}
 
-	if(puadi_xmlNewPropStr(dialog_node, "id", callid)==NULL) {
+	if(puadi_xmlNewPropStr(dialog_node, "id", uuid)==NULL) {
 		goto error;
 	}
 
@@ -289,7 +289,7 @@ error:
 void dialog_publish(char *state, str* ruri, str *entity, str *peer, str *callid,
 		unsigned int initiator, unsigned int lifetime, str *localtag,
 		str *remotetag, str *localtarget, str *remotetarget,
-		unsigned short do_pubruri_localcheck)
+		unsigned short do_pubruri_localcheck, str* uuid)
 {
 	str* body= NULL;
 	str uri= {NULL, 0};
@@ -319,7 +319,7 @@ void dialog_publish(char *state, str* ruri, str *entity, str *peer, str *callid,
 	content_type.len= 27;
 
 	body= build_dialoginfo(state, entity, peer, callid, initiator, localtag,
-			remotetag, localtarget, remotetarget);
+			remotetag, localtarget, remotetarget, uuid);
 	if(body == NULL || body->s == NULL)
 		goto error;
 
@@ -328,7 +328,7 @@ void dialog_publish(char *state, str* ruri, str *entity, str *peer, str *callid,
 	size= sizeof(publ_info_t)
 		+ sizeof(str) 			/* *pres_uri */
 		+ ( ruri->len 		/* pres_uri->s */
-				+ callid->len + 16	/* id.s */
+				+ uuid->len + 16	/* id.s */
 				+ content_type.len	/* content_type.s */
 			)*sizeof(char);
 
@@ -363,8 +363,8 @@ void dialog_publish(char *state, str* ruri, str *entity, str *peer, str *callid,
 	}
 	publ->id.s= (char*)publ+ size;
 	memcpy(publ->id.s, "DIALOG_PUBLISH.", 15);
-	memcpy(publ->id.s+15, callid->s, callid->len);
-	publ->id.len= 15+ callid->len;
+	memcpy(publ->id.s+15, uuid->s, uuid->len);
+	publ->id.len= 15+ uuid->len;
 	size+= publ->id.len;
 
 	publ->content_type.s= (char*)publ+ size;
@@ -411,14 +411,14 @@ void dialog_publish_multi(char *state, struct str_list* ruris, str *entity,
 		str *peer, str *callid, unsigned int initiator, unsigned int lifetime,
 		str *localtag, str *remotetag,
 		str *localtarget, str *remotetarget, unsigned short
-		do_pubruri_localcheck)
+		do_pubruri_localcheck, str *uuid)
 {
 	while(ruris) {
 		LM_DBG("CALLING dialog_publish for URI %.*s\n",
 				ruris->s.len, ruris->s.s);
 		dialog_publish(state,&(ruris->s),entity,peer,callid,initiator,
 				lifetime,localtag,remotetag,localtarget,remotetarget,
-				do_pubruri_localcheck);
+				do_pubruri_localcheck,uuid);
 		ruris=ruris->next;
 	}
 }
diff --git a/src/modules/pua_dialoginfo/pua_dialoginfo.c b/src/modules/pua_dialoginfo/pua_dialoginfo.c
index d5b1fea..bf622bd 100644
--- a/src/modules/pua_dialoginfo/pua_dialoginfo.c
+++ b/src/modules/pua_dialoginfo/pua_dialoginfo.c
@@ -42,6 +42,7 @@
 #include "../../core/mem/mem.h"
 #include "../../core/pt.h"
 #include "../../core/ut.h"
+#include "../../core/utils/sruid.h"
 #include "../dialog/dlg_load.h"
 #include "../dialog/dlg_hash.h"
 #include "../pua/pua_bind.h"
@@ -79,6 +80,7 @@ unsigned short pubruri_caller_avp_type;
 int_str pubruri_caller_avp_name;
 unsigned short pubruri_callee_avp_type;
 int_str pubruri_callee_avp_name;
+sruid_t _puadi_sruid;
 
 static str caller_dlg_var = {0, 0}; /* pubruri_caller */
 static str callee_dlg_var = {0, 0}; /* pubruri_callee */
@@ -107,7 +109,7 @@ send_publish_t pua_send_publish;
 /** module functions */
 
 static int mod_init(void);
-
+static int child_init(int rank);
 
 static cmd_export_t cmds[]={
 	{0, 0, 0, 0, 0, 0}
@@ -144,7 +146,7 @@ struct module_exports exports= {
 	0,					/* exported pseudo-variables */
 	0,					/* response handling function */
 	mod_init,			/* module initialization function */
-	0,					/* per-child init function */
+	child_init, 	/* per-child init function */
 	0					/* module destroy function */
 };
 
@@ -273,7 +275,7 @@ void refresh_pubruri_avps(struct dlginfo_cell *dlginfo, str *uri)
 				dialog_publish_multi("terminated", list,
 						&(dlginfo->from_uri), uri, &(dlginfo->callid), 1,
 						10, 0, 0, &(dlginfo->from_contact),
-						&target, send_publish_flag==-1?1:0);
+						&target, send_publish_flag==-1?1:0,&(dlginfo->uuid));
 				list->next = next;
 			}
 			list = list->next;
@@ -294,7 +296,7 @@ void refresh_pubruri_avps(struct dlginfo_cell *dlginfo, str *uri)
 				dialog_publish_multi("terminated", list,
 						uri, &(dlginfo->from_uri), &(dlginfo->callid), 0,
 						10, 0, 0, &target, &(dlginfo->from_contact),
-						send_publish_flag==-1?1:0);
+						send_publish_flag==-1?1:0,&(dlginfo->uuid));
 				list->next = next;
 			}
 			list = list->next;
@@ -366,7 +368,7 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 				dialog_publish_multi("terminated", dlginfo->pubruris_caller,
 						&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
 						10, 0, 0, &(dlginfo->from_contact),
-						&target, send_publish_flag==-1?1:0);
+						&target, send_publish_flag==-1?1:0,&(dlginfo->uuid));
 			}
 			if (disable_callee_publish_flag == -1 || !(request
 						&& (request->flags & (1<<disable_callee_publish_flag))))
@@ -374,7 +376,7 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 				dialog_publish_multi("terminated", dlginfo->pubruris_callee,
 						&uri, &(dlginfo->from_uri), &(dlginfo->callid), 0,
 						10, 0, 0, &target, &(dlginfo->from_contact),
-						send_publish_flag==-1?1:0);
+						send_publish_flag==-1?1:0,&(dlginfo->uuid));
 			}
 			break;
 		case DLGCB_CONFIRMED:
@@ -388,7 +390,7 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 				dialog_publish_multi("confirmed", dlginfo->pubruris_caller,
 						&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
 						dlginfo->lifetime, 0, 0, &(dlginfo->from_contact), &target,
-						send_publish_flag==-1?1:0);
+						send_publish_flag==-1?1:0,&(dlginfo->uuid));
 			}
 			if (disable_callee_publish_flag == -1 || !(request
 						&& (request->flags & (1<<disable_callee_publish_flag))))
@@ -396,7 +398,7 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 				dialog_publish_multi("confirmed", dlginfo->pubruris_callee, &uri,
 						&(dlginfo->from_uri), &(dlginfo->callid), 0,
 						dlginfo->lifetime, 0, 0, &target, &(dlginfo->from_contact),
-						send_publish_flag==-1?1:0);
+						send_publish_flag==-1?1:0,&(dlginfo->uuid));
 			}
 			break;
 		case DLGCB_EARLY:
@@ -438,13 +440,13 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 								&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
 								dlginfo->lifetime, &(dlginfo->from_tag), &tag,
 								&(dlginfo->from_contact), &target,
-								send_publish_flag==-1?1:0);
+								send_publish_flag==-1?1:0,&(dlginfo->uuid));
 					} else {
 						dialog_publish_multi("early", dlginfo->pubruris_caller,
 								&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
 								dlginfo->lifetime, &(dlginfo->from_tag), &tag,
 								&(dlginfo->from_contact), &target,
-								send_publish_flag==-1?1:0);
+								send_publish_flag==-1?1:0,&(dlginfo->uuid));
 					}
 				}
 				if (disable_callee_publish_flag == -1 || !(request &&
@@ -453,7 +455,7 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 					dialog_publish_multi("early", dlginfo->pubruris_callee, &uri,
 							&(dlginfo->from_uri), &(dlginfo->callid), 0,
 							dlginfo->lifetime, &tag, &(dlginfo->from_tag), &target,
-							&(dlginfo->from_contact), send_publish_flag==-1?1:0);
+							&(dlginfo->from_contact), send_publish_flag==-1?1:0,&(dlginfo->uuid));
 				}
 
 			} else {
@@ -464,13 +466,13 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 						dialog_publish_multi("confirmed", dlginfo->pubruris_caller,
 								&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
 								dlginfo->lifetime, 0, 0, &(dlginfo->from_contact),
-								&target, send_publish_flag==-1?1:0);
+								&target, send_publish_flag==-1?1:0,&(dlginfo->uuid));
 
 					} else {
 						dialog_publish_multi("early", dlginfo->pubruris_caller,
 								&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
 								dlginfo->lifetime, 0, 0, &(dlginfo->from_contact),
-								&target, send_publish_flag==-1?1:0);
+								&target, send_publish_flag==-1?1:0,&(dlginfo->uuid));
 					}
 				}
 				if (disable_callee_publish_flag == -1 || !(request
@@ -479,7 +481,7 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 					dialog_publish_multi("early", dlginfo->pubruris_callee, &uri,
 							&(dlginfo->from_uri), &(dlginfo->callid), 0,
 							dlginfo->lifetime, 0, 0, &target,
-							&(dlginfo->from_contact), send_publish_flag==-1?1:0);
+							&(dlginfo->from_contact), send_publish_flag==-1?1:0,&(dlginfo->uuid));
 				}
 			}
 			break;
@@ -492,7 +494,7 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 				dialog_publish_multi("terminated", dlginfo->pubruris_caller,
 						&(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
 						10, 0, 0, &(dlginfo->from_contact), &target,
-						send_publish_flag==-1?1:0);
+						send_publish_flag==-1?1:0,&(dlginfo->uuid));
 			}
 			if (disable_callee_publish_flag == -1 || !(request &&
 						(request->flags & (1<<disable_callee_publish_flag))))
@@ -500,7 +502,7 @@ __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_para
 				dialog_publish_multi("terminated", dlginfo->pubruris_callee, &uri,
 						&(dlginfo->from_uri), &(dlginfo->callid), 0,
 						10, 0, 0, &target, &(dlginfo->from_contact),
-						send_publish_flag==-1?1:0);
+						send_publish_flag==-1?1:0,&(dlginfo->uuid));
 			}
 	}
 	if(use_pubruri_avps && (refresh_pubruri_avps_flag > -1
@@ -565,6 +567,13 @@ struct dlginfo_cell* get_dialog_data(struct dlg_cell *dlg, int type)
 	int len;
 	str* s=NULL;
 
+	// generate new random uuid
+	if(sruid_next_safe(&_puadi_sruid) < 0) {
+		return NULL;
+	}
+	LM_DBG("uuid generated: '%.*s'\n",
+		_puadi_sruid.uid.len, _puadi_sruid.uid.s);
+
 	/* create dlginfo structure to store important data inside the module*/
 	len = sizeof(struct dlginfo_cell)
 		+ dlg->from_uri.len
@@ -572,7 +581,8 @@ struct dlginfo_cell* get_dialog_data(struct dlg_cell *dlg, int type)
 		+ dlg->callid.len
 		+ dlg->tag[0].len
 		+ dlg->req_uri.len
-		+ dlg->contact[0].len;
+		+ dlg->contact[0].len
+		+ _puadi_sruid.uid.len;
 
 	dlginfo = (struct dlginfo_cell*)shm_malloc( len );
 	if (dlginfo==0) {
@@ -599,6 +609,8 @@ struct dlginfo_cell* get_dialog_data(struct dlg_cell *dlg, int type)
 	dlginfo->req_uri.len  = dlg->req_uri.len;
 	dlginfo->from_contact.s   = dlginfo->req_uri.s + dlginfo->req_uri.len;
 	dlginfo->from_contact.len = dlg->contact[0].len;
+	dlginfo->uuid.s = dlginfo->from_contact.s + dlginfo->from_contact.len;
+	dlginfo->uuid.len = _puadi_sruid.uid.len;
 
 	memcpy(dlginfo->from_uri.s, dlg->from_uri.s, dlg->from_uri.len);
 	memcpy(dlginfo->to_uri.s, dlg->to_uri.s, dlg->to_uri.len);
@@ -606,6 +618,7 @@ struct dlginfo_cell* get_dialog_data(struct dlg_cell *dlg, int type)
 	memcpy(dlginfo->from_tag.s, dlg->tag[0].s, dlg->tag[0].len);
 	memcpy(dlginfo->req_uri.s, dlg->req_uri.s, dlg->req_uri.len);
 	memcpy(dlginfo->from_contact.s, dlg->contact[0].s, dlg->contact[0].len);
+	memcpy(dlginfo->uuid.s, _puadi_sruid.uid.s, _puadi_sruid.uid.len);
 
 	if (use_pubruri_avps) {
 		if(type==DLGCB_CREATED) {
@@ -740,7 +753,7 @@ __dialog_created(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
 				&(dlg->from_uri),
 				(include_req_uri)?&(dlg->req_uri):&(dlg->to_uri),
 				&(dlg->callid), 1, dlginfo->lifetime,
-				0, 0, 0, 0, (send_publish_flag==-1)?1:0);
+				0, 0, 0, 0, (send_publish_flag==-1)?1:0,&(dlginfo->uuid));
 		if(use_pubruri_avps) lock_release(&dlginfo->lock);
 	}
 
@@ -752,7 +765,7 @@ __dialog_created(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
 				(include_req_uri)?&(dlg->req_uri):&(dlg->to_uri),
 				&(dlg->from_uri),
 				&(dlg->callid), 0, dlginfo->lifetime,
-				0, 0, 0, 0, (send_publish_flag==-1)?1:0);
+				0, 0, 0, 0, (send_publish_flag==-1)?1:0,&(dlginfo->uuid));
 		if(use_pubruri_avps) lock_release(&dlginfo->lock);
 	}
 }
@@ -784,6 +797,10 @@ static int mod_init(void)
 	str s;
 	pv_spec_t avp_spec;
 
+	if(sruid_init(&_puadi_sruid, (char)'-', "padi", SRUID_INC)<0) {
+		return -1;
+	}
+
 	if(caller_dlg_var.len<=0) {
 		LM_WARN("pubruri_caller_dlg_var is not set"
 				" - restore on restart disabled\n");
@@ -866,6 +883,22 @@ static int mod_init(void)
 	return 0;
 }
 
+/**
+ * @brief Initialize module children
+ */
+static int child_init(int rank)
+{
+	if(sruid_init(&_puadi_sruid, (char)'-', "padi", SRUID_INC)<0) {
+		return -1;
+	}
+
+	if(rank != PROC_MAIN) {
+		return 0;
+	}
+
+	return 0;
+}
+
 void free_dlginfo_cell(void *param) {
 
 	struct dlginfo_cell *cell = NULL;
diff --git a/src/modules/pua_dialoginfo/pua_dialoginfo.h b/src/modules/pua_dialoginfo/pua_dialoginfo.h
index 8289669..8d3757d 100644
--- a/src/modules/pua_dialoginfo/pua_dialoginfo.h
+++ b/src/modules/pua_dialoginfo/pua_dialoginfo.h
@@ -30,7 +30,7 @@ extern send_publish_t pua_send_publish;
 
 void dialog_publish_multi(char *state, struct str_list* ruris, str *entity, str *peer, str *callid,
 	unsigned int initiator, unsigned int lifetime, str *localtag, str *remotetag,
-	str *localtarget, str *remotetarget, unsigned short do_pubruri_localcheck);
+	str *localtarget, str *remotetarget, unsigned short do_pubruri_localcheck, str *uuid);
 
 /* store the important data locally to avoid reading the data from the
  * dlg_cell during the callback (as this could create a race condition
@@ -47,6 +47,7 @@ struct dlginfo_cell {
 	struct str_list* pubruris_caller;
 	struct str_list* pubruris_callee;
 	unsigned int lifetime;
+	str uuid;
 };
 
 
