Browse code

- added support for XMPP presence and BLA - added a new column in database table- "pua" - added the possibility to have callbacks for received replies

git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@1954 689a6050-402a-0410-94f2-e92a70836424

Anca Vamanu authored on 04/04/2007 08:59:00
Showing 14 changed files
... ...
@@ -38,6 +38,8 @@ Anca-Maria Vamanu
38 38
         2.1. bind_pua(pua_api_t* api)
39 39
         2.2. send_publish(publ_info_t*)
40 40
         2.3. send_subscribe(subs_info_t*)
41
+        2.4. pua_is_dialog(ua_prea_t*)
42
+        2.5. register_puacb(int types, pua_cb f, void* param)
41 43
 
42 44
    3. Frequently Asked Questions
43 45
 
... ...
@@ -50,6 +52,8 @@ Anca-Maria Vamanu
50 52
    1-6. Set update_period parameter
51 53
    1-7. PUA tables
52 54
    2-1. pua_api structure
55
+   2-2. pua_is_dialog usage example
56
+   2-3. register_puacb usage example
53 57
      _________________________________________________________
54 58
 
55 59
 Chapter 1. User's Guide
... ...
@@ -60,12 +64,16 @@ Chapter 1. User's Guide
60 64
    client, sending Subscribe and Publish messages.
61 65
 
62 66
    Now it can be used with the following modules: pua_mi and
63
-   pua_usrloc. The pua_mi offer the possiblity to publish any
64
-   kind of information or subscribing to a resource through fifo.
65
-   The pua_usrloc module calls a function exported by pua modules
66
-   to publish elementary presence information, such as basic
67
-   status "open" or "closed", for clients that do not implement
68
-   client-to-server presence.
67
+   pua_usrloc, pua_bla and pua_xmpp. The pua_mi offer the
68
+   possibility to publish any kind of information or subscribing
69
+   to a resource through fifo. The pua_usrloc module calls a
70
+   function exported by pua modules to publish elementary
71
+   presence information, such as basic status "open" or "closed",
72
+   for clients that do not implement client-to-server presence.
73
+   Through pua_bla , BRIDGED LINE APPEARANCE features are added
74
+   to openser. The pua_xmpp module represents a gateway between
75
+   SIP and XMPP, so that jabber and SIP clients can exchange
76
+   presence information.
69 77
 
70 78
    The module use cache to store presentity list and writes to
71 79
    database on timer to be able to recover upon restart.
... ...
@@ -187,6 +195,7 @@ CREATE TABLE pua (
187 195
   id int(10) unsigned NOT NULL auto_increment,
188 196
   pres_uri varchar(128) NOT NULL,
189 197
   pres_id varchar(128) NOT NULL,
198
+  event int(11) NOT NULL,
190 199
   expires int(11) NOT NULL,
191 200
   flag int(11) NOT NULL,
192 201
   etag varchar(128) NOT NULL,
... ...
@@ -196,6 +205,7 @@ CREATE TABLE pua (
196 205
   to_tag varchar(128) NOT NULL,
197 206
   from_tag varchar(128) NOT NULL,
198 207
   cseq int(11) NOT NULL,
208
+  version int(11) NOT NULL,
199 209
   PRIMARY KEY  (`id`)
200 210
 ) ENGINE=MyISAM;
201 211
 
... ...
@@ -274,6 +284,43 @@ typedef struct subs_info
274 284
 ...
275 285
      _________________________________________________________
276 286
 
287
+2.4. pua_is_dialog(ua_prea_t*)
288
+
289
+   This function checks is the parameter coresponds to a stored
290
+   Subscribe initiated dialog.
291
+
292
+   Example 2-2. pua_is_dialog usage example
293
+...
294
+        if(pua_is_dialog(dialog)< 0)
295
+        {
296
+                LOG(L_ERR, "ERROR while querying dialog\n");
297
+                goto error;
298
+        }
299
+...
300
+     _________________________________________________________
301
+
302
+2.5. register_puacb(int types, pua_cb f, void* param)
303
+
304
+   This function registers a callback to be called on receiving
305
+   the reply message for the sent request( Publish or Subscribe).
306
+   The type parameter should be set the same as the source_flag
307
+   for that request. The function registered as callback for pua
308
+   should be of type pua_cb , which is: typedef void
309
+   (pua_cb)(ua_pres_t* hentity, struct msg_start * fl); The
310
+   parameters are the dialog structure for that request and the
311
+   first line of the reply message.
312
+
313
+   Example 2-3. register_puacb usage example
314
+...
315
+        if(pua.register_puacb(XMPP_SUBSCRIBE, Sipreply2Xmpp, NULL)< 0)
316
+        {
317
+                LOG(L_ERR, "PUA_XMPP:mod_init Could not register
318
+                callback\n");
319
+                return -1;
320
+        }
321
+...
322
+     _________________________________________________________
323
+
277 324
 Chapter 3. Frequently Asked Questions
278 325
 
279 326
    3.1. Where can I find more about OpenSER?
... ...
@@ -5,6 +5,7 @@ CREATE TABLE pua (
5 5
   id int(10) unsigned NOT NULL auto_increment,
6 6
   pres_uri varchar(128) NOT NULL,
7 7
   pres_id varchar(128) NOT NULL,
8
+  event int(11) NOT NULL,  
8 9
   expires int(11) NOT NULL,
9 10
   flag int(11) NOT NULL,
10 11
   etag varchar(128) NOT NULL,
... ...
@@ -14,6 +15,7 @@ CREATE TABLE pua (
14 15
   to_tag varchar(128) NOT NULL,
15 16
   from_tag varchar(128) NOT NULL,
16 17
   cseq int(11) NOT NULL,
18
+  version int(11) NOT NULL,
17 19
   PRIMARY KEY  (`id`)
18 20
 ) ENGINE=MyISAM;
19 21
 
... ...
@@ -100,6 +100,55 @@ typedef struct subs_info
100 100
 </programlisting>
101 101
 		</para>
102 102
 	</section>
103
+	<section>
104
+		<title>
105
+			<function moreinfo="none">pua_is_dialog(ua_prea_t*)</function>
106
+		</title>
107
+		<para>
108
+			This function checks is the parameter coresponds to a stored
109
+			Subscribe initiated dialog. 
110
+		</para>
111
+		<example>
112
+		<title><function>pua_is_dialog </function>usage example</title>
113
+	<programlisting format="linespecific">
114
+...	
115
+	if(pua_is_dialog(dialog)< 0)
116
+	{
117
+		LOG(L_ERR, "ERROR while querying dialog\n");
118
+		goto error;
119
+	}
120
+...	
121
+</programlisting>
122
+		</example>
123
+		</section>
124
+		<section>
125
+		<title>
126
+			<function moreinfo="none">register_puacb(int types, pua_cb f, void* param)</function>
127
+		</title>
128
+		<para>
129
+			This function registers a callback to be called on receiving the reply message
130
+			for the sent request( Publish or Subscribe).
131
+			The type parameter should be set the same as the source_flag for that request.
132
+			The function registered as callback for pua should be of type pua_cb , which is:
133
+			typedef void (pua_cb)(ua_pres_t* hentity, struct msg_start * fl);
134
+			The parameters are the dialog structure for that request and the first line of the
135
+			reply message.
136
+		</para>
137
+		<example>
138
+		<title><function>register_puacb </function>usage example</title>
139
+	<programlisting format="linespecific">
140
+...
141
+	if(pua.register_puacb(XMPP_SUBSCRIBE, Sipreply2Xmpp, NULL)< 0)
142
+	{
143
+		LOG(L_ERR, "PUA_XMPP:mod_init Could not register
144
+		callback\n");
145
+		return -1;
146
+	}
147
+...	
148
+	</programlisting>
149
+		</example>
150
+
151
+		</section>
103 152
 </chapter>
104 153
 
105 154
 <!-- Keep this element at the end of the file
... ...
@@ -18,12 +18,16 @@
18 18
 		sending Subscribe and Publish messages. 
19 19
 	</para>
20 20
 	<para>
21
-		 Now it can be used with the following modules: pua_mi and pua_usrloc.
22
-		 The pua_mi offer the possiblity to publish any kind of information
21
+		 Now it can be used with the following modules: pua_mi and pua_usrloc,
22
+		 pua_bla and pua_xmpp.
23
+		 The pua_mi offer the possibility to publish any kind of information
23 24
 		 or subscribing to a resource through fifo. The pua_usrloc module calls
24 25
 		 a function exported by pua modules to publish elementary presence
25 26
 		 information, such as basic status "open" or "closed", for clients that
26
-		 do not implement client-to-server presence.  
27
+		 do not implement client-to-server presence.
28
+		 Through pua_bla , BRIDGED LINE APPEARANCE features are added to openser.
29
+		 The pua_xmpp module represents a gateway between SIP and XMPP, so that 
30
+		 jabber and SIP clients can exchange presence information. 
27 31
 	</para>
28 32
 	<para>
29 33
 		The module use cache to store presentity list and writes to database
... ...
@@ -92,27 +92,31 @@ error:
92 92
 
93 93
 }
94 94
 
95
-ua_pres_t* search_htable(str* pres_uri, str* watcher_uri, str id,
96
-		int FLAG, int event,unsigned int hash_code)
95
+
96
+ua_pres_t* search_htable(str* pres_uri, str* watcher_uri, int FLAG, 
97
+		str id, unsigned int hash_code)
97 98
 {
98 99
 	ua_pres_t* p= NULL,* L= NULL;
99 100
  
100 101
 	L= HashT->p_records[hash_code].entity;
101 102
 	DBG("PUA: search_htable: core_hash= %u\n", hash_code);
103
+	if(FLAG& BLA_SUBSCRIBE)
104
+	{
105
+		DBG("PUA: search_htable: Search BLA_SUBSCRIBE_FLAG\n");
106
+	}
102 107
 
103 108
 	for(p= L->next; p; p=p->next)
104 109
 	{
105
-		if((p->event== event) && (p->flag & FLAG))
110
+
111
+		if(p->flag & FLAG)
106 112
 		{
107 113
 			DBG("PUA: search_htable:pres_uri= %.*s len= %d\n",
108 114
 					p->pres_uri->len, p->pres_uri->s, p->pres_uri->len);
109 115
 			DBG("PUA: search_htable:searched uri= %.*s len= %d\n",
110 116
 					pres_uri->len,pres_uri->s, pres_uri->len);
111
-
112 117
 			if((p->pres_uri->len==pres_uri->len) &&
113 118
 					(strncmp(p->pres_uri->s, pres_uri->s,pres_uri->len)==0))
114 119
 			{
115
-				DBG("PUA: search_htable:found pres_ur\n");
116 120
 				if(watcher_uri)
117 121
 				{
118 122
 					if(p->watcher_uri->len==watcher_uri->len &&
... ...
@@ -126,7 +130,6 @@ ua_pres_t* search_htable(str* pres_uri, str* watcher_uri, str id,
126 130
 				{
127 131
 					if(id.s)
128 132
 					{	
129
-						DBG("PUA: search_htable: compare id\n");
130 133
 						if(id.len== p->id.len &&
131 134
 								strncmp(p->id.s, id.s, id.len)==0)
132 135
 							break;
... ...
@@ -151,7 +154,7 @@ void update_htable(ua_pres_t* presentity,time_t desired_expires, int expires, un
151 154
 	DBG("PUA:hash_update ..\n");
152 155
 
153 156
 	p= search_htable(presentity->pres_uri, presentity->watcher_uri,
154
-				presentity->id, presentity->flag,presentity->event, hash_code);
157
+				 presentity->flag, presentity->id, hash_code);
155 158
 	if(p== NULL)
156 159
 	{
157 160
 		DBG("PUA:hash_update : no recod found\n");
... ...
@@ -167,7 +170,7 @@ void update_htable(ua_pres_t* presentity,time_t desired_expires, int expires, un
167 170
 		p->cseq ++;
168 171
 
169 172
 }
170
-
173
+/* insert in front; so when searching the most recent result is returned*/
171 174
 void insert_htable(ua_pres_t* presentity)
172 175
 {
173 176
 	ua_pres_t* p= NULL;
... ...
@@ -175,22 +178,22 @@ void insert_htable(ua_pres_t* presentity)
175 178
 
176 179
 	hash_code= core_hash(presentity->pres_uri,presentity->watcher_uri, 
177 180
 			HASH_SIZE);
178
-
181
+	
179 182
 	if(presentity->expires < (int)time(NULL))
180 183
 	{
181 184
 		LOG(L_ERR, "PUA: insert_htable: expired information- do not insert\n");
182 185
 		return;
183 186
 	}
184
-
185 187
 	lock_get(&HashT->p_records[hash_code].lock);
186 188
 
187
-	p= search_htable(presentity->pres_uri, presentity->watcher_uri,
188
-				presentity->id, presentity->flag, presentity->event, hash_code);
189
-	if(p) 
189
+/*	
190
+ *	useless since always checking before calling insert
191
+	if(get_dialog(presentity, hash_code)!= NULL )
190 192
 	{
191
-		lock_release(& HashT->p_records[hash_code].lock);
193
+		DBG("PUA: insert_htable: Dialog already found- do not insert\n");
192 194
 		return; 
193 195
 	}
196
+*/	
194 197
 	p= HashT->p_records[hash_code].entity;
195 198
 
196 199
 	presentity->db_flag= INSERTDB_FLAG;
... ...
@@ -199,19 +202,16 @@ void insert_htable(ua_pres_t* presentity)
199 202
 	p->next= presentity;
200 203
 
201 204
 	lock_release(&HashT->p_records[hash_code].lock);
205
+
202 206
 }
203 207
 
204
-void delete_htable(ua_pres_t* presentity)
208
+void delete_htable(ua_pres_t* presentity, unsigned int hash_code)
205 209
 { 
206 210
 	ua_pres_t* p= NULL, *q= NULL;
207
-	unsigned int hash_code;
208 211
 	DBG("PUA:delete_htable...\n");
209 212
 
210
-	hash_code= core_hash(presentity->pres_uri,presentity->watcher_uri, 
211
-			HASH_SIZE);
212
-
213 213
 	p= search_htable(presentity->pres_uri, presentity->watcher_uri,
214
-			presentity->id, presentity->flag, presentity->event, hash_code);
214
+			 presentity->flag, presentity->id, hash_code);
215 215
 	if(p== NULL)
216 216
 		return;
217 217
 
... ...
@@ -251,3 +251,56 @@ void destroy_htable()
251 251
   return;
252 252
 }
253 253
 
254
+/* must lock the record line before calling this function*/
255
+ua_pres_t* get_dialog(ua_pres_t* dialog, unsigned int hash_code)
256
+{
257
+	ua_pres_t* p= NULL, *L;
258
+	DBG("PUA: get_dialog: core_hash= %u\n", hash_code);
259
+
260
+	L= HashT->p_records[hash_code].entity;
261
+	for(p= L->next; p; p=p->next)
262
+	{
263
+
264
+		if(p->flag& dialog->flag)
265
+		{
266
+			DBG("PUA: get_dialog: pres_uri= %.*s\twatcher_uri=%.*s\n\tcallid= %.*s\tto_tag= %.*s\tfrom_tag= %.*s\n",
267
+					p->pres_uri->len, p->pres_uri->s, p->watcher_uri->len, p->watcher_uri->s,
268
+					p->call_id.len, p->call_id.s, p->to_tag.len, p->to_tag.s, p->from_tag.len, p->from_tag.s);
269
+
270
+			DBG("PUA: get_dialog: searched to_tag= %.*s\tfrom_tag= %.*s\n",
271
+					 p->to_tag.len, p->to_tag.s, p->from_tag.len, p->from_tag.s);
272
+	    	if((p->pres_uri->len== dialog->pres_uri->len) &&
273
+				(strncmp(p->pres_uri->s, dialog->pres_uri->s,p->pres_uri->len)==0)&&
274
+				(p->watcher_uri->len== dialog->watcher_uri->len) &&
275
+				(strncmp(p->watcher_uri->s, dialog->watcher_uri->s, p->watcher_uri->len )==0)&&
276
+				(strncmp(p->call_id.s, dialog->call_id.s, p->call_id.len)== 0) &&
277
+				(strncmp(p->to_tag.s, dialog->to_tag.s, p->to_tag.len)== 0) &&
278
+				(strncmp(p->from_tag.s, dialog->from_tag.s, p->from_tag.len)== 0) )
279
+				{	
280
+					DBG("PUA: get_dialog: FOUND dialog\n");
281
+					break;
282
+				}
283
+		}	
284
+	
285
+	}
286
+		
287
+	return p;
288
+}	
289
+int is_dialog(ua_pres_t* dialog)
290
+{
291
+	int ret_code= 0;
292
+	unsigned int hash_code;
293
+	
294
+	hash_code= core_hash(dialog->pres_uri, dialog->watcher_uri, HASH_SIZE);
295
+	lock_get(&HashT->p_records[hash_code].lock);
296
+
297
+	if(get_dialog(dialog, hash_code)== NULL)
298
+		ret_code= -1;
299
+	else
300
+		ret_code= 0;
301
+	lock_release(&HashT->p_records[hash_code].lock);
302
+	
303
+	return ret_code;
304
+
305
+}
306
+
... ...
@@ -32,33 +32,23 @@
32 32
 #include "../../str.h"
33 33
 #include "../../lock_ops.h"
34 34
 
35
-#define UL_PUBLISH			1<<0
36
-#define MI_PUBLISH			1<<1
37
-#define MI_SUBSCRIBE		1<<2
38
-#define END2END_PUBLISH		1<<3
39
-#define END2END_SUBSCRIBE   1<<4
40
-#define XMPP_PUBLISH		1<<5
41
-#define XMPP_SUBSCRIBE      1<<6
35
+#define UL_PUBLISH					1<<0
36
+#define BLA_PUBLISH					1<<1
37
+#define BLA_SUBSCRIBE				1<<2
38
+#define XMPP_PUBLISH				1<<3
39
+#define XMPP_SUBSCRIBE				1<<4
40
+#define XMPP_INITIAL_SUBS		    1<<5
41
+#define MI_PUBLISH					1<<6
42
+#define MI_SUBSCRIBE				1<<7
42 43
 
43 44
 #define PRESENCE_EVENT      1<<0
44 45
 #define PWINFO_EVENT        1<<1
45
-
46
+#define BLA_EVENT			1<<2
46 47
 
47 48
 #define NO_UPDATEDB_FLAG	1<<0
48 49
 #define UPDATEDB_FLAG		1<<1
49 50
 #define INSERTDB_FLAG		1<<2
50 51
 
51
-typedef struct hentity
52
-{
53
-	str* pres_uri;
54
-	str* watcher_uri;
55
-	str id;
56
-	str tuple_id;
57
-	int event;
58
-	int flag;
59
-	int desired_expires;
60
-}hentity_t;
61
-
62 52
 typedef struct ua_pres{
63 53
  
64 54
     /* common*/
... ...
@@ -70,18 +60,20 @@ typedef struct ua_pres{
70 60
 	int flag;
71 61
 	int db_flag;
72 62
 	struct ua_pres* next;
73
-
63
+	
74 64
 	/* publish */
75 65
 	str etag;
76 66
 	str tuple_id;
77
-	
67
+	str* body;
78 68
 	/* subscribe */
79 69
 	str* watcher_uri;
80 70
 	str call_id;
81 71
 	str to_tag;
82 72
     str from_tag;
83 73
 	int cseq;
84
-	
74
+	int version;
75
+      int watcher_count;
76
+ /*?? should this be long? */
85 77
 }ua_pres_t;
86 78
 
87 79
 typedef struct hash_entry
... ...
@@ -96,17 +88,19 @@ typedef struct htable{
96 88
 
97 89
 htable_t* new_htable();
98 90
 
99
-ua_pres_t* search_htable(str* pres_uri, str* watcher_uri, str id, 
100
-		int FLAG, int event, unsigned int hash_code);
91
+ua_pres_t* search_htable(str* pres_uri, str* watcher_uri, int FLAG,
92
+		str id, unsigned int hash_code);
101 93
 
102 94
 void insert_htable(ua_pres_t* presentity );
103 95
 
104 96
 void update_htable(ua_pres_t* presentity,time_t desired_expires,
105 97
 		int expires, unsigned int hash_code);
106 98
 
107
-void delete_htable(ua_pres_t* presentity );
99
+void delete_htable(ua_pres_t* presentity, unsigned int hash_code);
108 100
 
109 101
 void destroy_htable();
102
+int is_dialog(ua_pres_t* dialog);
103
+ua_pres_t* get_dialog(ua_pres_t* dialog, unsigned int hash_code);
110 104
 
111
-
105
+typedef int  (*query_dialog_t)(ua_pres_t* presentity);
112 106
 #endif
... ...
@@ -47,8 +47,10 @@
47 47
 #include "send_publish.h"
48 48
 #include "send_subscribe.h"
49 49
 #include "pua_bind.h"
50
+#include "pua_callback.h"
50 51
 
51 52
 MODULE_VERSION
53
+#define PUA_TABLE_VERSION 2
52 54
 
53 55
 struct tm_binds tmb;
54 56
 htable_t* HashT= NULL;
... ...
@@ -74,7 +76,7 @@ static void destroy(void);
74 76
 int send_subscribe(subs_info_t*);
75 77
 int send_publish(publ_info_t*);
76 78
 
77
-int update_pua(ua_pres_t* p);
79
+int update_pua(ua_pres_t* p, unsigned int hash_code);
78 80
 
79 81
 int db_store();
80 82
 int db_restore();
... ...
@@ -83,10 +85,12 @@ void hashT_clean(unsigned int ticks,void *param);
83 85
 
84 86
 static cmd_export_t cmds[]=
85 87
 {
86
-	{"bind_pua",	   (cmd_function)bind_pua,		   1, 0, 0},
87
-	{"send_publish",   (cmd_function)send_publish,     1, 0, 0},
88
-	{"send_subscribe", (cmd_function)send_subscribe,   1, 0, 0},
89
-	{0,							0,					   0, 0, 0} 
88
+	{"bind_pua",	     (cmd_function)bind_pua,		 1, 0, 0},
89
+	{"send_publish",     (cmd_function)send_publish,     1, 0, 0},
90
+	{"send_subscribe",   (cmd_function)send_subscribe,   1, 0, 0},
91
+	{"pua_is_dialog",    (cmd_function)is_dialog,		 1, 0, 0},
92
+	{"register_puacb", (cmd_function)register_puacb,     1, 0, 0},
93
+	{0,							0,					     0, 0, 0} 
90 94
 };
91 95
 
92 96
 static param_export_t params[]={
... ...
@@ -120,6 +124,9 @@ struct module_exports exports= {
120 124
  */
121 125
 static int mod_init(void)
122 126
 {
127
+	str _s;
128
+	int ver = 0;
129
+	
123 130
 	load_tm_f  load_tm;
124 131
 
125 132
 	DBG("PUA: initializing module ...\n");
... ...
@@ -165,6 +172,16 @@ static int mod_init(void)
165 172
 		LOG(L_ERR,"PUA:mod_init: Error while connecting database\n");
166 173
 		return -1;
167 174
 	}
175
+	// verify table version 
176
+	_s.s = db_table;
177
+	_s.len = strlen(db_table);
178
+	 ver =  table_version(&pua_dbf, pua_db, &_s);
179
+	if(ver!=PUA_TABLE_VERSION)
180
+	{
181
+		LOG(L_ERR,"PRESENCE:mod_init: Wrong version v%d for table <%s>,"
182
+				" need v%d\n", ver, _s.s, PUA_TABLE_VERSION);
183
+		return -1;
184
+	}
168 185
 
169 186
 	if(HASH_SIZE<=1)
170 187
 		HASH_SIZE= 512;
... ...
@@ -188,10 +205,15 @@ static int mod_init(void)
188 205
 		DBG("PUA: ERROR: mod_init: wrong clean_period \n");
189 206
 		return -1;
190 207
 	}
208
+	if ( init_puacb_list() < 0)
209
+    {
210
+		LOG(L_ERR, "PUA:mod_init: ERROR: callbacks initialization failed\n");
211
+        return -1;
212
+    }
191 213
 
192 214
 	startup_time = (int) time(NULL);
193 215
 	
194
-	register_timer(hashT_clean, 0, update_period);
216
+	register_timer(hashT_clean, 0, update_period- 5);
195 217
 
196 218
 	register_timer(db_update, 0, update_period);
197 219
 
... ...
@@ -236,8 +258,11 @@ static int child_init(int rank)
236 258
 static void destroy(void)
237 259
 {	
238 260
 	DBG("PUA: destroying module ...\n");
261
+	if (puacb_list)
262
+		destroy_puacb_list();
239 263
 
240
-	db_update(0,0);
264
+	if(pua_db && HashT)
265
+		db_update(0,0);
241 266
 	
242 267
 	if(HashT)
243 268
 		destroy_htable();
... ...
@@ -251,7 +276,7 @@ static void destroy(void)
251 276
 int db_restore()
252 277
 {
253 278
 	ua_pres_t* p= NULL;
254
-	db_key_t result_cols[12]; 
279
+	db_key_t result_cols[13]; 
255 280
 	db_res_t *res= NULL;
256 281
 	db_row_t *row = NULL;	
257 282
 	db_val_t *row_vals= NULL;
... ...
@@ -260,19 +285,23 @@ int db_restore()
260 285
 	str watcher_uri, call_id;
261 286
 	str to_tag, from_tag;
262 287
 	int size= 0, i;
288
+	int n_result_cols= 0;
289
+	int puri_col,pid_col,expires_col,flag_col,etag_col,tuple_col;
290
+	int watcher_col,callid_col,totag_col,fromtag_col,cseq_col,event_col;
291
+
292
+	result_cols[puri_col=n_result_cols++]	="pres_uri";		
293
+	result_cols[pid_col=n_result_cols++]	="pres_id";	
294
+	result_cols[expires_col=n_result_cols++]="expires";
295
+	result_cols[flag_col=n_result_cols++]	="flag";
296
+	result_cols[etag_col=n_result_cols++]	="etag";
297
+	result_cols[tuple_col=n_result_cols++]	="tuple_id";
298
+	result_cols[watcher_col=n_result_cols++]="watcher_uri";
299
+	result_cols[callid_col=n_result_cols++] ="call_id";
300
+	result_cols[totag_col=n_result_cols++]	="to_tag";
301
+	result_cols[fromtag_col=n_result_cols++]="from_tag";
302
+	result_cols[cseq_col= n_result_cols++]	="cseq";
303
+	result_cols[event_col= n_result_cols++]	="event";
263 304
 	
264
-	result_cols[0] ="pres_uri";		
265
-	result_cols[1] ="pres_id";	
266
-	result_cols[2] ="expires";
267
-	result_cols[3] ="flag";
268
-	result_cols[4] ="etag";
269
-	result_cols[5] ="tuple_id";
270
-	result_cols[6] ="watcher_uri";
271
-	result_cols[7] ="call_id";
272
-	result_cols[8] ="to_tag";
273
-	result_cols[9] ="from_tag";
274
-	result_cols[10]="cseq";
275
-
276 305
 	if(!pua_db)
277 306
 	{
278 307
 		LOG(L_ERR,"PUA: db_restore: ERROR null database connection\n");
... ...
@@ -285,7 +314,7 @@ int db_restore()
285 314
 		return -1;
286 315
 	}
287 316
 
288
-	if(pua_dbf.query(pua_db,0, 0, 0, result_cols,0, 11, 0,&res)< 0)
317
+	if(pua_dbf.query(pua_db,0, 0, 0, result_cols,0, n_result_cols, 0,&res)< 0)
289 318
 	{
290 319
 		LOG(L_ERR, "PUA: db_restore:ERROR while querrying table\n");
291 320
 		if(res)
... ...
@@ -328,25 +357,25 @@ int db_restore()
328 357
 
329 358
 		if(row_vals[4].val.str_val.s)
330 359
 		{
331
-			etag.s= row_vals[4].val.str_val.s;
360
+			etag.s= row_vals[etag_col].val.str_val.s;
332 361
 			etag.len = strlen(etag.s);
333 362
 	
334
-			tuple_id.s= row_vals[5].val.str_val.s;
363
+			tuple_id.s= row_vals[tuple_col].val.str_val.s;
335 364
 			tuple_id.len = strlen(tuple_id.s);
336 365
 		}
337 366
 
338 367
 		if(row_vals[6].val.str_val.s)
339 368
 		{	
340
-			watcher_uri.s= row_vals[6].val.str_val.s;
369
+			watcher_uri.s= row_vals[watcher_col].val.str_val.s;
341 370
 			watcher_uri.len = strlen(watcher_uri.s);
342 371
 	
343
-			call_id.s= row_vals[7].val.str_val.s;
372
+			call_id.s= row_vals[callid_col].val.str_val.s;
344 373
 			call_id.len = strlen(call_id.s);
345 374
 
346
-			to_tag.s= row_vals[8].val.str_val.s;
375
+			to_tag.s= row_vals[totag_col].val.str_val.s;
347 376
 			to_tag.len = strlen(to_tag.s);
348 377
 
349
-			from_tag.s= row_vals[9].val.str_val.s;
378
+			from_tag.s= row_vals[fromtag_col].val.str_val.s;
350 379
 			from_tag.len = strlen(from_tag.s);
351 380
 		}
352 381
 		
... ...
@@ -377,8 +406,8 @@ int db_restore()
377 406
 		p->id.len= pres_id.len;
378 407
 		size+= pres_id.len;
379 408
 
380
-		p->expires= row_vals[2].val.int_val;
381
-		p->flag|=	row_vals[3].val.int_val;
409
+		p->expires= row_vals[expires_col].val.int_val;
410
+		p->flag|=	row_vals[flag_col].val.int_val;
382 411
 		p->db_flag|= INSERTDB_FLAG;
383 412
 
384 413
 		if(etag.len)
... ...
@@ -418,9 +447,10 @@ int db_restore()
418 447
 			p->call_id.len= call_id.len;
419 448
 			size+= call_id.len;
420 449
 
421
-			p->cseq= row_vals[10].val.int_val;
450
+			p->cseq= row_vals[cseq_col].val.int_val;
422 451
 		}
423
-		
452
+		p->event= row_vals[event_col].val.int_val;
453
+
424 454
 		insert_htable(p);
425 455
 	}
426 456
 	if(res)
... ...
@@ -449,57 +479,64 @@ error:
449 479
 void hashT_clean(unsigned int ticks,void *param)
450 480
 {
451 481
 	int i;
482
+	time_t now;
452 483
 	ua_pres_t* p= NULL, *q= NULL;
453 484
 
454 485
 	DBG("PUA: hashT_clean ..\n");
455
-
486
+	now = time(NULL);
456 487
 	for(i= 0;i< HASH_SIZE; i++)
457 488
 	{
458 489
 		lock_get(&HashT->p_records[i].lock);
459 490
 		p= HashT->p_records[i].entity->next;
460 491
 		while(p)
461 492
 		{	
462
-			if(p->expires< (int)(time)(NULL)+10)
493
+			if(p->expires- update_period < now )
463 494
 			{
464
-				if(p->desired_expires> p->expires+ 10 || (p->desired_expires && p->watcher_uri))
495
+				if((p->desired_expires> p->expires + min_expires) || 
496
+						(p->desired_expires== 0 ))
465 497
 				{
466
-					if(update_pua(p)< 0)
498
+					if(update_pua(p, i)< 0)
467 499
 					{
468 500
 						LOG(L_ERR, "PUA: hashT_clean: Error while updating\n");
469 501
 						lock_release(&HashT->p_records[i].lock);
470 502
 						return;
471
-					}	
472
-				}
473
-				p= p->next;
474
-			}
475
-			else
476
-				if(p->expires< (int)(time)(NULL))
503
+					}
504
+					p= p->next;
505
+					continue;
506
+				}	
507
+			    if(p->expires < now - 2)
477 508
 				{
478 509
 					q= p->next;
479
-					delete_htable(p);
510
+					DBG("PUA: hashT_clean: Found expired: uri= %.*s\n", p->pres_uri->len,
511
+							p->pres_uri->s);
512
+					delete_htable(p, i);
480 513
 					p= q;
481 514
 				}
482 515
 				else
483 516
 					p= p->next;
517
+			}	
518
+			else
519
+				p= p->next;
484 520
 		}
485 521
 		lock_release(&HashT->p_records[i].lock);
486 522
 	}
487 523
 
488 524
 }
489
-int update_pua(ua_pres_t* p)
525
+int update_pua(ua_pres_t* p, unsigned int hash_code)
490 526
 {
491 527
 	int size= 0;
492
-	hentity_t* hentity= NULL;
528
+	ua_pres_t* hentity= NULL;
493 529
 	str* str_hdr= NULL;
530
+	int expires;
494 531
 
495
-	size= sizeof(hentity_t)+ sizeof(str)+ (p->pres_uri->len+ 1)*sizeof(char);
532
+	size= sizeof(ua_pres_t)+ sizeof(str)+ (p->pres_uri->len+ 1)*sizeof(char);
496 533
 	
497 534
 	if(p->watcher_uri)
498 535
 		size+= sizeof(str)+ p->watcher_uri->len;
499 536
 	else
500 537
 		size+=  p->id.len;
501 538
 
502
-	hentity= (hentity_t*)shm_malloc(size);
539
+	hentity= (ua_pres_t*)shm_malloc(size);
503 540
 	if(hentity== NULL)
504 541
 	{
505 542
 		LOG(L_ERR, "PUA: update_pua: ERROR no more share memory\n");
... ...
@@ -507,7 +544,7 @@ int update_pua(ua_pres_t* p)
507 544
 	}
508 545
 	memset(hentity, 0, size);
509 546
 
510
-	size =  sizeof(hentity_t);
547
+	size =  sizeof(ua_pres_t);
511 548
 
512 549
 	hentity->pres_uri = (str*)((char*)hentity + size);
513 550
 	size+= sizeof(str);
... ...
@@ -534,21 +571,25 @@ int update_pua(ua_pres_t* p)
534 571
 		hentity->id.len= p->id.len;
535 572
 		size+= p->id.len;
536 573
 	}
537
-
538 574
 	hentity->flag|= p->flag;
539 575
 	
576
+	if(p->desired_expires== 0)
577
+			expires= 3600;
578
+		else
579
+			expires= p->desired_expires- (int)time(NULL);
540 580
 
541 581
 	if(p->watcher_uri== NULL)
542 582
 	{
543 583
 		str met= {"PUBLISH", 7};
544
-		str_hdr = publ_build_hdr(p->desired_expires- (int)time(NULL), &p->etag, 0);
584
+		str_hdr = publ_build_hdr(expires, p->event, &p->etag, NULL, 0);
545 585
 		if(str_hdr == NULL)
546 586
 		{
547 587
 			LOG(L_ERR, "PUA: update_pua: ERROR while building extra_headers\n");
548 588
 			goto error;
549 589
 		}
550 590
 		DBG("PUA: update_pua: str_hdr:\n%.*s\n ", str_hdr->len, str_hdr->s);
551
-	
591
+		
592
+		
552 593
 		tmb.t_request(&met,						/* Type of the message */
553 594
 				p->pres_uri,					/* Request-URI */
554 595
 				p->pres_uri,					/* To */
... ...
@@ -558,10 +599,10 @@ int update_pua(ua_pres_t* p)
558 599
 				publ_cback_func,				/* Callback function */
559 600
 				(void*)hentity					/* Callback parameter */
560 601
 				);
602
+		
561 603
 	}
562 604
 	else
563 605
 	{
564
-		int expires;
565 606
 		str met= {"SUBSCRIBE", 9};
566 607
 		dlg_t* td= NULL;
567 608
 		td= pua_build_dlg_t(p);
... ...
@@ -570,19 +611,16 @@ int update_pua(ua_pres_t* p)
570 611
 			LOG(L_ERR, "PUA:update_pua: Error while building tm dlg_t"
571 612
 					"structure");		
572 613
 			goto error;
573
-		}
574
-		if(p->desired_expires== 0)
575
-			expires= 3600;
576
-		else
577
-			expires= p->desired_expires- (int)time(NULL);
578
-
614
+		};
615
+	
579 616
 		str_hdr= subs_build_hdr(p->watcher_uri, expires, p->event);
580 617
 		if(str_hdr== NULL || str_hdr->s== NULL)
581 618
 		{
582 619
 			LOG(L_ERR, "PUA:send_subscribe: Error while building extra headers\n");
620
+			pkg_free(td);
583 621
 			return -1;
584 622
 		}
585
-
623
+		
586 624
 		tmb.t_request_within
587 625
 		(&met,
588 626
 		str_hdr,                               
... ...
@@ -611,7 +649,7 @@ error:
611 649
 void db_update(unsigned int ticks,void *param)
612 650
 {
613 651
 	ua_pres_t* p= NULL;
614
-	db_key_t q_cols[13];
652
+	db_key_t q_cols[14];
615 653
 	db_res_t *res= NULL;
616 654
 	db_key_t db_cols[3];
617 655
 	db_val_t q_vals[13], db_vals[3];
... ...
@@ -619,52 +657,75 @@ void db_update(unsigned int ticks,void *param)
619 657
 	int n_query_cols= 0;
620 658
 	int n_update_cols= 0;
621 659
 	int i;
660
+	int puri_col,pid_col,expires_col,flag_col,etag_col,tuple_col;
661
+	int watcher_col,callid_col,totag_col,fromtag_col,cseq_col,event_col;
662
+	int no_lock= 0;
622 663
 	
623
-	/* cols and values used for insert */
624
-	q_cols[0] ="pres_uri";
625
-	q_vals[0].type = DB_STR;
626
-	q_vals[0].nul = 0;
664
+	if(ticks== 0 && param == NULL)
665
+		no_lock= 1;
627 666
 
628
-	q_cols[1] ="pres_id";	
629
-	q_vals[1].type = DB_STR;
630
-	q_vals[1].nul = 0;
631 667
 
632
-	q_cols[2] ="flag";
633
-	q_vals[2].type = DB_INT;
634
-	q_vals[2].nul = 0;
635
-
636
-	q_cols[3] ="watcher_uri";
637
-	q_vals[3].type = DB_STR;
638
-	q_vals[3].nul = 0;
639
-
640
-	q_cols[4] ="tuple_id";
641
-	q_vals[4].type = DB_STR;
642
-	q_vals[4].nul = 0;
643
-
644
-	q_cols[5] ="etag";
645
-	q_vals[5].type = DB_STR;
646
-	q_vals[5].nul = 0;
647
-	
648
-	q_cols[6] ="call_id";
649
-	q_vals[6].type = DB_STR;
650
-	q_vals[6].nul = 0;
651
-
652
-	q_cols[7] ="to_tag";
653
-	q_vals[7].type = DB_STR;
654
-	q_vals[7].nul = 0;
655
-	
656
-	q_cols[8] ="from_tag";
657
-	q_vals[8].type = DB_STR;
658
-	q_vals[8].nul = 0;
668
+	DBG("PUA: db_update...\n");
669
+	/* cols and values used for insert */
670
+	q_cols[puri_col= n_query_cols] ="pres_uri";
671
+	q_vals[puri_col= n_query_cols].type = DB_STR;
672
+	q_vals[puri_col= n_query_cols].nul = 0;
673
+	n_query_cols++;
659 674
 	
660
-	q_cols[9]="cseq";
661
-	q_vals[9].type = DB_INT;
662
-	q_vals[9].nul = 0;
675
+	q_cols[pid_col= n_query_cols] ="pres_id";	
676
+	q_vals[pid_col= n_query_cols].type = DB_STR;
677
+	q_vals[pid_col= n_query_cols].nul = 0;
678
+	n_query_cols++;
679
+
680
+	q_cols[flag_col= n_query_cols] ="flag";
681
+	q_vals[flag_col= n_query_cols].type = DB_INT;
682
+	q_vals[flag_col= n_query_cols].nul = 0;
683
+	n_query_cols++;
684
+	q_cols[watcher_col= n_query_cols] ="watcher_uri";
685
+	q_vals[watcher_col= n_query_cols].type = DB_STR;
686
+	q_vals[watcher_col= n_query_cols].nul = 0;
687
+	n_query_cols++;
688
+
689
+	q_cols[tuple_col= n_query_cols] ="tuple_id";
690
+	q_vals[tuple_col= n_query_cols].type = DB_STR;
691
+	q_vals[tuple_col= n_query_cols].nul = 0;
692
+	n_query_cols++;
693
+
694
+	q_cols[etag_col= n_query_cols] ="etag";
695
+	q_vals[etag_col= n_query_cols].type = DB_STR;
696
+	q_vals[etag_col= n_query_cols].nul = 0;
697
+	n_query_cols++;	
698
+
699
+	q_cols[callid_col= n_query_cols] ="call_id";
700
+	q_vals[callid_col= n_query_cols].type = DB_STR;
701
+	q_vals[callid_col= n_query_cols].nul = 0;
702
+	n_query_cols++;
703
+
704
+	q_cols[totag_col= n_query_cols] ="to_tag";
705
+	q_vals[totag_col= n_query_cols].type = DB_STR;
706
+	q_vals[totag_col= n_query_cols].nul = 0;
707
+	n_query_cols++;
708
+
709
+	q_cols[fromtag_col= n_query_cols] ="from_tag";
710
+	q_vals[fromtag_col= n_query_cols].type = DB_STR;
711
+	q_vals[fromtag_col= n_query_cols].nul = 0;
712
+	n_query_cols++;
713
+
714
+	q_cols[cseq_col= n_query_cols]="cseq";
715
+	q_vals[cseq_col= n_query_cols].type = DB_INT;
716
+	q_vals[cseq_col= n_query_cols].nul = 0;
717
+	n_query_cols++;
718
+
719
+	q_cols[expires_col= n_query_cols] ="expires";
720
+	q_vals[expires_col= n_query_cols].type = DB_INT;
721
+	q_vals[expires_col= n_query_cols].nul = 0;
722
+	n_query_cols++;
723
+
724
+	q_cols[event_col= n_query_cols] ="event";
725
+	q_vals[event_col= n_query_cols].type = DB_INT;
726
+	q_vals[event_col= n_query_cols].nul = 0;
727
+	n_query_cols++;
663 728
 
664
-	q_cols[10] ="expires";
665
-	q_vals[10].type = DB_INT;
666
-	q_vals[10].nul = 0;
667
-	
668 729
 	/* cols and values used for update */
669 730
 	db_cols[0]= "expires";
670 731
 	db_vals[0].type = DB_INT;
... ...
@@ -674,14 +735,11 @@ void db_update(unsigned int ticks,void *param)
674 735
 	db_vals[1].type = DB_INT;
675 736
 	db_vals[1].nul = 0;
676 737
 
677
-	DBG("PUA:db_update ...\n");
678
-	
679 738
 	if(pua_db== NULL)
680 739
 	{
681 740
 		LOG(L_ERR,"PUA: db_update: ERROR null database connection\n");
682 741
 		return;
683 742
 	}
684
-
685 743
 	if(pua_dbf.use_table(pua_db, db_table)< 0)
686 744
 	{
687 745
 		LOG(L_ERR, "PUA: db_update:ERROR in use table\n");
... ...
@@ -690,7 +748,9 @@ void db_update(unsigned int ticks,void *param)
690 748
 
691 749
 	for(i=0; i<HASH_SIZE; i++) 
692 750
 	{
693
-		lock_get(&HashT->p_records[i].lock);	
751
+		if(!no_lock)
752
+			lock_get(&HashT->p_records[i].lock);	
753
+		
694 754
 		p = HashT->p_records[i].entity->next;
695 755
 		while(p)
696 756
 		{
... ...
@@ -715,9 +775,9 @@ void db_update(unsigned int ticks,void *param)
715 775
 					n_update_cols= 1;
716 776
 					n_query_cols= 3;
717 777
 					
718
-					q_vals[0].val.str_val = *(p->pres_uri);
719
-					q_vals[1].val.str_val = p->id;
720
-					q_vals[2].val.int_val = p->flag;
778
+					q_vals[puri_col].val.str_val = *(p->pres_uri);
779
+					q_vals[pid_col].val.str_val = p->id;
780
+					q_vals[flag_col].val.int_val = p->flag;
721 781
 
722 782
 					db_vals[0].val.int_val= p->expires;
723 783
 					
... ...
@@ -775,22 +835,23 @@ void db_update(unsigned int ticks,void *param)
775 835
 				case INSERTDB_FLAG:
776 836
 				{	
777 837
 					DBG("PUA: db_update: INSERTDB_FLAG\n ");
778
-					q_vals[0].val.str_val = *(p->pres_uri);
779
-					q_vals[1].val.str_val = p->id;
780
-					q_vals[2].val.int_val = p->flag;
838
+					q_vals[puri_col].val.str_val = *(p->pres_uri);
839
+					q_vals[pid_col].val.str_val = p->id;
840
+					q_vals[flag_col].val.int_val = p->flag;
781 841
 					if((p->watcher_uri))
782
-						q_vals[3].val.str_val = *(p->watcher_uri);
842
+						q_vals[watcher_col].val.str_val = *(p->watcher_uri);
783 843
 					else
784
-						memset(& q_vals[3].val.str_val ,0, sizeof(str));
785
-					q_vals[4].val.str_val = p->tuple_id;
786
-					q_vals[5].val.str_val = p->etag;
787
-					q_vals[6].val.str_val = p->call_id;
788
-					q_vals[7].val.str_val = p->to_tag;
789
-					q_vals[8].val.str_val = p->from_tag;
790
-					q_vals[9].val.int_val= p->cseq;
791
-					q_vals[10].val.int_val = p->expires;
844
+						memset(& q_vals[watcher_col].val.str_val ,0, sizeof(str));
845
+					q_vals[tuple_col].val.str_val = p->tuple_id;
846
+					q_vals[etag_col].val.str_val = p->etag;
847
+					q_vals[callid_col].val.str_val = p->call_id;
848
+					q_vals[totag_col].val.str_val = p->to_tag;
849
+					q_vals[fromtag_col].val.str_val = p->from_tag;
850
+					q_vals[cseq_col].val.int_val= p->cseq;
851
+					q_vals[expires_col].val.int_val = p->expires;
852
+					q_vals[event_col].val.int_val = p->event;
792 853
 						
793
-					if(pua_dbf.insert(pua_db, q_cols, q_vals, 11)<0)
854
+					if(pua_dbf.insert(pua_db, q_cols, q_vals, 12)<0)
794 855
 					{
795 856
 						LOG(L_ERR, "PUA: db_update: ERROR while inserting"
796 857
 								" into table pua\n");
... ...
@@ -807,7 +868,8 @@ void db_update(unsigned int ticks,void *param)
807 868
 			}
808 869
 			p= p->next;
809 870
 		}
810
-		lock_release(&HashT->p_records[i].lock);	
871
+		if(!no_lock)
872
+			lock_release(&HashT->p_records[i].lock);	
811 873
 	}
812 874
 
813 875
 	db_vals[0].val.int_val= (int)time(NULL);
... ...
@@ -28,8 +28,8 @@
28 28
 #include "../../str.h"
29 29
 #include "hash.h"
30 30
 
31
-#define INSERT_TYPE  1<<0
32
-#define UPDATE_TYPE  1<<1
31
+#define INSERT_TYPE  1<<1
32
+#define UPDATE_TYPE  1<<2
33 33
 
34 34
 extern str default_domain;
35 35
 extern struct tm_binds tmb;
... ...
@@ -25,8 +25,6 @@
25 25
 
26 26
 #include "pua_bind.h"
27 27
 #include "../../dprint.h"
28
-#include "../../sr_module.h"
29
-
30 28
 
31 29
 int bind_pua(pua_api_t* api)
32 30
 {
... ...
@@ -50,6 +48,19 @@ int bind_pua(pua_api_t* api)
50 48
 		LOG(L_ERR, "PUA:bind_pua: Can't bind send_subscribe\n");
51 49
 		return -1;
52 50
 	}
51
+	api->register_puacb = ( register_puacb_t)find_export
52
+		("register_puacb", 1, 0);
53
+	if (api->register_puacb == 0)
54
+	{
55
+		LOG(L_ERR, "PUA:bind_pua: Can't bind send_subscribe\n");
56
+		return -1;
57
+	}
58
+	api->is_dialog= (query_dialog_t)find_export("pua_is_dialog", 1, 0);
59
+	if(api->is_dialog== 0)
60
+	{
61
+		LOG(L_ERR, "PUA:bind_pua: Can't bind pua_is_dialog\n");
62
+		return -1;
63
+	}
53 64
 	return 0;
54 65
 }
55 66
 
... ...
@@ -27,10 +27,13 @@
27 27
 #define PUA_API_H
28 28
 #include "send_subscribe.h"
29 29
 #include "send_publish.h"
30
+#include "pua_callback.h"
30 31
 
31 32
 typedef struct pua_api {
32 33
 	send_subscribe_t send_subscribe;
33 34
 	send_publish_t send_publish;
35
+	register_puacb_t register_puacb;
36
+	query_dialog_t is_dialog;
34 37
 } pua_api_t;
35 38
 
36 39
 typedef int (*bind_pua_t)(pua_api_t* api);
... ...
@@ -81,7 +81,7 @@ char *xmlNodeGetAttrContentByName(xmlNodePtr node, const char *name)
81 81
 		return NULL;
82 82
 }
83 83
 
84
-void print_hentity(hentity_t* h)
84
+void print_hentity(ua_pres_t* h)
85 85
 {
86 86
 	DBG("\tpresentity:\n");
87 87
 	DBG("\turi= %.*s\n", h->pres_uri->len, h->pres_uri->s);
... ...
@@ -93,7 +93,7 @@ void print_hentity(hentity_t* h)
93 93
 		DBG("\ttuple_id: %.*s\n", h->tuple_id.len, h->tuple_id.s);
94 94
 }	
95 95
 
96
-str* publ_build_hdr(int expires, str* etag, int is_body)
96
+str* publ_build_hdr(int expires, int event, str* etag, str* extra_headers, int is_body)
97 97
 {
98 98
 	static char buf[3000];
99 99
 	str* str_hdr = NULL;	
... ...
@@ -108,11 +108,28 @@ str* publ_build_hdr(int expires, str* etag, int is_body)
108 108
 		LOG(L_ERR, "PUA: publ_build_hdr:ERROR while allocating memory\n");
109 109
 		return NULL;
110 110
 	}
111
-
111
+	memset(str_hdr, 0 , sizeof(str));
112
+	memset(buf, 0, 2999);
112 113
 	str_hdr->s = buf;
114
+	str_hdr->len= 0;
113 115
 
114
-	memcpy(str_hdr->s ,"Event: presence", 15);
115
-	str_hdr->len = 15;
116
+	if(event & PRESENCE_EVENT)
117
+	{
118
+		memcpy(str_hdr->s ,"Event: presence", 15);
119
+		str_hdr->len = 15;
120
+	}
121
+	else
122
+	if(event & BLA_EVENT)	
123
+	{
124
+		memcpy(str_hdr->s ,"Event: dialog;sla", 17);
125
+		str_hdr->len = 17;	
126
+	}
127
+	else
128
+	{
129
+		LOG(L_ERR, "PUA: publ_build_hdr:ERROR BAD event value\n");
130
+		pkg_free(str_hdr);
131
+		return NULL;
132
+	}	
116 133
 	memcpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
117 134
 	str_hdr->len += CRLF_LEN;
118 135
 	
... ...
@@ -137,7 +154,7 @@ str* publ_build_hdr(int expires, str* etag, int is_body)
137 154
 	memcpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
138 155
 	str_hdr->len += CRLF_LEN;
139 156
 	
140
-	if( etag)
157
+	if(etag)
141 158
 	{
142 159
 		DBG("PUA:publ_build_hdr: UPDATE_TYPE\n");
143 160
 		memcpy(str_hdr->s+str_hdr->len,"SIP-If-Match: ", 14);
... ...
@@ -154,6 +171,12 @@ str* publ_build_hdr(int expires, str* etag, int is_body)
154 171
 		memcpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
155 172
 		str_hdr->len += CRLF_LEN;
156 173
 	}
174
+
175
+	if(extra_headers && extra_headers->s && extra_headers->len)
176
+	{
177
+		memcpy(str_hdr->s+str_hdr->len,extra_headers->s , extra_headers->len);
178
+		str_hdr->len += extra_headers->len;
179
+	}	
157 180
 	str_hdr->s[str_hdr->len] = '\0';
158 181
 	
159 182
 	return str_hdr;
... ...
@@ -164,6 +187,7 @@ void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
164 187
 	struct hdr_field* hdr= NULL;
165 188
 	struct sip_msg* msg= NULL;
166 189
 	ua_pres_t* presentity= NULL;
190
+	ua_pres_t* hentity= NULL;
167 191
 	int found = 0;
168 192
 	int size= 0;
169 193
 	int lexpire= 0;
... ...
@@ -175,7 +199,6 @@ void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
175 199
 		LOG(L_ERR, "PUA:publ_cback_func: Error NULL callback parameter\n");
176 200
 		goto done;
177 201
 	}
178
-
179 202
 	if( ps->code>= 300 )
180 203
 	{
181 204
 		if( *ps->param== NULL ) 
... ...
@@ -183,32 +206,57 @@ void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
183 206
 			DBG("PUA publ_cback_func: NULL callback parameter\n");
184 207
 			return;
185 208
 		}
186
-
187
-		hash_code= core_hash(((hentity_t*)(*ps->param))->pres_uri, NULL,
188
-				HASH_SIZE);
209
+		hentity= (ua_pres_t*)(*ps->param);
210
+		hash_code= core_hash(hentity->pres_uri, NULL,
211
+					HASH_SIZE);
189 212
 		lock_get(&HashT->p_records[hash_code].lock);
190
-
191
-		presentity= search_htable(((hentity_t*)(*ps->param))->pres_uri, NULL,
192
-				((hentity_t*)(*ps->param))->id,
193
-				((hentity_t*)(*ps->param))->flag,
194
-				((hentity_t*)(*ps->param))->event, hash_code);
213
+		presentity= search_htable( hentity->pres_uri, NULL, hentity->flag,
214
+								   hentity->id, hash_code);
195 215
 		if(presentity)
196 216
 		{
197
-			delete_htable(presentity);
198
-			DBG("PUA:publ_cback_func: ***Delete from table\n");
217
+			if(ps->code== 412 && hentity->body)
218
+			{
219
+				/* sent a PUBLISH within a dialog that no longer exists
220
+				 * send again an intial PUBLISH */
221
+				DBG("PUA:publ_cback_func: received s 412 reply- send an"
222
+						" INSERT_TYPE publish request\n");
223
+				delete_htable(presentity, hash_code);
224
+				lock_release(&HashT->p_records[hash_code].lock);
225
+				publ_info_t publ;
226
+				memset(&publ, 0, sizeof(publ_info_t));
227
+				publ.pres_uri= hentity->pres_uri; 
228
+				publ.body= hentity->body;
229
+				publ.expires= (hentity->desired_expires>0)?
230
+					hentity->desired_expires- (int)time(NULL)+ 10:-1;
231
+				publ.flag|= INSERT_TYPE;
232
+				publ.source_flag|= hentity->flag;
233
+				publ.event|= hentity->event;
234
+				publ.id= hentity->id;
235
+				if(send_publish(&publ)< 0)
236
+				{
237
+					LOG(L_ERR, "PUA:publ_cback_func: ERROR when trying to send PUBLISH\n");
238
+					goto done;
239
+				}
240
+			}
241
+			else
242
+			{	
243
+				delete_htable(presentity, hash_code);
244
+				DBG("PUA:publ_cback_func: ***Delete from table\n");
245
+				lock_release(&HashT->p_records[hash_code].lock);
246
+			}
199 247
 		}
200
-		lock_release(&HashT->p_records[hash_code].lock);
248
+		else
249
+			lock_release(&HashT->p_records[hash_code].lock);
201 250
 		goto done;
202 251
 	}
203 252
 
204
-	
205 253
 	msg= ps->rpl;
206 254
 	if(msg == NULL || msg== FAKED_REPLY)
207 255
 	{
208 256
 		LOG(L_ERR, "PUA:publ_cback_func: ERROR no reply message found\n ");
209 257
 		goto done;
210 258
 	}
211
-	if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
259
+	if( parse_headers(msg,HDR_EOH_F, 0)==-1 )
212 260
 	{
213 261
 		LOG(L_ERR, "PUA:publ_cback_func: error parsing headers\n");
214 262
 		goto done;
... ...
@@ -237,37 +285,35 @@ void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
237 285
 	{
238 286
 		DBG("PUA publ_cback_func: Error NULL callback parameter\n");
239 287
 		return;
240
-	}	
288
+	}
289
+	hentity= (ua_pres_t*)(*ps->param);
290
+
241 291
 	LOG(L_DBG, "PUA:publ_cback_func: completed with status %d [contact:"
242
-			"%.*s]\n",ps->code, ((hentity_t*)(*ps->param))->pres_uri->len, 
243
-			((hentity_t*)(*ps->param))->pres_uri->s);
292
+			"%.*s]\n",ps->code, hentity->pres_uri->len, hentity->pres_uri->s);
244 293
 
245 294
 	DBG("PUA: publ_cback_func: searched presentity:\n");
246
-	print_hentity( ((hentity_t*)(*ps->param)) );
295
+	print_hentity( hentity);
247 296
 
248
-	hash_code= core_hash(((hentity_t*)(*ps->param))->pres_uri, NULL, HASH_SIZE);
297
+	hash_code= core_hash(hentity->pres_uri, NULL, HASH_SIZE);
249 298
 	lock_get(&HashT->p_records[hash_code].lock);
250
-
251
-	presentity= search_htable(((hentity_t*)(*ps->param))->pres_uri, NULL,
252
-				((hentity_t*)(*ps->param))->id,
253
-				((hentity_t*)(*ps->param))->flag,
254
-				((hentity_t*)(*ps->param))->event, hash_code);
299
+	
300
+	presentity= search_htable(hentity->pres_uri, NULL,hentity->flag,
301
+			hentity->id, hash_code);
255 302
 	if(presentity)
256 303
 	{
257 304
 			DBG("PUA:publ_cback_func: update record\n");
258 305
 			if(lexpire == 0)
259 306
 			{
260 307
 				DBG("PUA:publ_cback_func: expires= 0- delete from htable\n"); 
261
-				delete_htable(presentity);
308
+				delete_htable(presentity, hash_code);
262 309
 				lock_release(&HashT->p_records[hash_code].lock);
263 310
 				goto done;
264 311
 			}
265
-			update_htable(presentity, ((hentity_t*)(*ps->param))->desired_expires,
312
+			update_htable(presentity, hentity->desired_expires,
266 313
 					lexpire, hash_code);
267 314
 			lock_release(&HashT->p_records[hash_code].lock);
268 315
 			goto done;
269 316
 	}
270
-
271 317
 	lock_release(&HashT->p_records[hash_code].lock);
272 318
 
273 319
 	if(lexpire== 0)
... ...
@@ -292,9 +338,9 @@ void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
292 338
 	}
293 339
 	etag= hdr->body;
294 340
 	size= sizeof(ua_pres_t)+ sizeof(str)+ 
295
-		(((hentity_t*)(*ps->param))->pres_uri->len+etag.len+ 
296
-		 ((hentity_t*)(*ps->param))->tuple_id.len + 
297
-		 ((hentity_t*)(*ps->param))->id.len+ 1)* sizeof(char);
341
+		(((ua_pres_t*)(*ps->param))->pres_uri->len+etag.len+ 
342
+		 ((ua_pres_t*)(*ps->param))->tuple_id.len + 
343
+		 ((ua_pres_t*)(*ps->param))->id.len+ 1)* sizeof(char);
298 344
 	presentity= (ua_pres_t*)shm_malloc(size);
299 345
 	if(presentity== NULL)
300 346
 	{
... ...
@@ -308,11 +354,11 @@ void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
308 354
 
309 355
 	presentity->pres_uri->s= (char*)presentity+ size;
310 356
 	memcpy(presentity->pres_uri->s,
311
-			((hentity_t*)(*ps->param))->pres_uri->s,
312
-			((hentity_t*)(*ps->param))->pres_uri->len);
357
+			((ua_pres_t*)(*ps->param))->pres_uri->s,
358
+			((ua_pres_t*)(*ps->param))->pres_uri->len);
313 359
 	presentity->pres_uri->len= 
314
-		((hentity_t*)(*ps->param))->pres_uri->len;
315
-	size+= ((hentity_t*)(*ps->param))->pres_uri->len;
360
+		((ua_pres_t*)(*ps->param))->pres_uri->len;
361
+	size+= ((ua_pres_t*)(*ps->param))->pres_uri->len;
316 362
 	presentity->etag.s= (char*)presentity+ size;
317 363
 	memcpy(presentity->etag.s, etag.s, etag.len);
318 364
 	presentity->etag.len= etag.len;
... ...
@@ -320,21 +366,21 @@ void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
320 366
 
321 367
 	presentity->tuple_id.s= (char*)presentity+ size;
322 368
 	memcpy(presentity->tuple_id.s,
323
-			((hentity_t*)(*ps->param))->tuple_id.s,
324
-			((hentity_t*)(*ps->param))->tuple_id.len);
325
-	presentity->tuple_id.len= ((hentity_t*)(*ps->param))->tuple_id.len;
369
+			((ua_pres_t*)(*ps->param))->tuple_id.s,
370
+			((ua_pres_t*)(*ps->param))->tuple_id.len);
371
+	presentity->tuple_id.len= ((ua_pres_t*)(*ps->param))->tuple_id.len;
326 372
 	size+= presentity->tuple_id.len;
327 373
 
328 374
 	presentity->id.s=(char*)presentity+ size;
329
-	memcpy(presentity->id.s, ((hentity_t*)(*ps->param))->id.s, 
330
-			((hentity_t*)(*ps->param))->id.len);
331
-	presentity->id.len= ((hentity_t*)(*ps->param))->id.len; 
375
+	memcpy(presentity->id.s, ((ua_pres_t*)(*ps->param))->id.s, 
376
+			((ua_pres_t*)(*ps->param))->id.len);
377
+	presentity->id.len= ((ua_pres_t*)(*ps->param))->id.len; 
332 378
 	size+= presentity->id.len;
333 379
 		
334 380
 	presentity->expires= lexpire +(int)time(NULL);
335
-	presentity->desired_expires= ((hentity_t*)(*ps->param))->desired_expires;
336
-	presentity->flag|= ((hentity_t*)(*ps->param))->flag;
337
-	presentity->event= PRESENCE_EVENT;
381
+	presentity->desired_expires= ((ua_pres_t*)(*ps->param))->desired_expires;
382
+	presentity->flag|= ((ua_pres_t*)(*ps->param))->flag;
383
+	presentity->event|= ((ua_pres_t*)(*ps->param))->event;
338 384
 	presentity->db_flag|= INSERTDB_FLAG;
339 385
 
340 386
 	insert_htable( presentity);
... ...
@@ -357,15 +403,16 @@ int send_publish( publ_info_t* publ )
357 403
 	str* str_hdr = NULL;
358 404
 	ua_pres_t* presentity= NULL;
359 405
 	char buf[50];
360
-	int size= 0;
406
+	unsigned int size= 0;
361 407
 	str* body= NULL;
362 408
 	xmlDocPtr doc= NULL;
363 409
 	xmlNodePtr node= NULL;
364 410
 	char* tuple_id= NULL, *person_id= NULL;
365 411
 	int tuple_id_len= 0;
366
-	hentity_t* hentity= NULL;
412
+	ua_pres_t* hentity= NULL;
367 413
 	unsigned int hash_code;
368 414
 	str etag= {0, 0};
415
+	int ver= 0;
369 416
 
370 417
 	DBG("PUA: send_publish for: uri=%.*s\n", publ->pres_uri->len,
371 418
 			publ->pres_uri->s );
... ...
@@ -373,25 +420,30 @@ int send_publish( publ_info_t* publ )
373 420
 	hash_code= core_hash(publ->pres_uri, NULL, HASH_SIZE);
374 421
 
375 422
 	lock_get(&HashT->p_records[hash_code].lock);
423
+	
424
+	presentity= search_htable(publ->pres_uri, NULL,
425
+			     publ->source_flag, publ->id,hash_code);
376 426
 
377
-	presentity= search_htable( publ->pres_uri, NULL,
378
-				publ->id, publ->source_flag, PRESENCE_EVENT,hash_code);
379
-
427
+	if(publ->flag & INSERT_TYPE)
428
+		goto insert;
429
+	
380 430
 	if(presentity== NULL)
381 431
 	{
432
+insert:	
382 433
 		lock_release(&HashT->p_records[hash_code].lock);
383
-
434
+		DBG("PUA: send_publish: insert type\n"); 
435
+		
436
+		if(publ->flag & UPDATE_TYPE )
437
+		{
438
+			DBG("PUA: send_publish: UPDATE_TYPE and no record found \n");
439
+			publ->flag= INSERT_TYPE;
440
+		}
384 441
 		if(publ->expires== 0)
385 442
 		{
386 443
 			DBG("PUA: send_publish: request for a publish with expires 0 and"
387 444
 					" no record found\n");
388 445
 			return 0;
389 446
 		}
390
-		if(publ->flag & UPDATE_TYPE )
391
-		{
392
-			DBG("PUA: send_publish: UPDATE_TYPE and no record found \n");
393
-			publ->flag= INSERT_TYPE;
394
-		}
395 447
 		if(publ->body== NULL)
396 448
 		{
397 449
 			LOG(L_INFO, "PUA: send_publish: New PUBLISH and no body found\n");
... ...
@@ -400,7 +452,7 @@ int send_publish( publ_info_t* publ )
400 452
 	}
401 453
 	else
402 454
 	{
403
-		DBG("UPDATE TYPE\n");
455
+		publ->flag= UPDATE_TYPE;
404 456
 		etag.s= (char*)pkg_malloc(presentity->etag.len* sizeof(char));
405 457
 		if(etag.s== NULL)
406 458
 		{
... ...
@@ -414,29 +466,63 @@ int send_publish( publ_info_t* publ )
414 466
 		if(publ->expires== 0)
415 467
 		{
416 468
 			DBG("PUA:send_publish: expires= 0- delete from hash table\n");
417
-			delete_htable(presentity);
469
+			delete_htable(presentity, hash_code);
418 470
 			presentity= NULL;
419 471
 			lock_release(&HashT->p_records[hash_code].lock);
420 472
 			goto send_publish;
421 473
 		}
474
+		presentity->version++;
475
+		ver= presentity->version;
422 476
 		lock_release(&HashT->p_records[hash_code].lock);
423
-		
424
-		publ->flag|= UPDATE_TYPE;
425 477