Browse code

- included memory caching storage with the possibility to configure a fallback to database mode

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

Anca Vamanu authored on 16/08/2007 07:35:58
Showing 23 changed files
... ...
@@ -33,6 +33,7 @@ Anca-Maria Vamanu
33 33
               1.3.8. expires_offset (int)
34 34
               1.3.9. max_expires (int)
35 35
               1.3.10. server_address (str)
36
+              1.3.11. fallback2db (int)
36 37
 
37 38
         1.4. Exported Functions
38 39
 
... ...
@@ -65,8 +66,9 @@ Anca-Maria Vamanu
65 66
    1-8. Set expires_offset parameter
66 67
    1-9. Set max_expires parameter
67 68
    1-10. Set server_address parameter
68
-   1-11. handle_publish usage
69
-   1-12. handle_subscribe usage
69
+   1-11. Set fallback2db parameter
70
+   1-12. handle_publish usage
71
+   1-13. handle_subscribe usage
70 72
    2-1. event_api_t structure
71 73
      _________________________________________________________
72 74
 
... ...
@@ -81,14 +83,23 @@ Chapter 1. User's Guide
81 83
    presence.winfo, dialog;sla from presence_xml module and
82 84
    message-summary from presence_mwi module.
83 85
 
84
-   The presence server works with database storage. It stores
85
-   published information and Subscribe -Notify dialog
86
-   characteristics.
87
-
88
-   It can also work only with the functionality of a library,
89
-   with no message processing and generation, but used only for
90
-   the exported functions. This mode of operation is enabled if
91
-   the db_url parameter is not set to any value.
86
+   The modules uses database storage. It has later been improved
87
+   with memory caching operations to improve performance. The
88
+   Subscribe dialog information are stored in memory and are
89
+   periodically updated in database, while for Publish only the
90
+   presence or absence of stored info for a certain resource is
91
+   maintained in memory to avoid unnecessary, costly db
92
+   operations. It is possible to configure a fallback to database
93
+   mode(by setting module parameter "fallback2db"). In this mode,
94
+   in case a searched record is not found in cache, the search is
95
+   continued in database. This is useful for an architecture in
96
+   which processing and memory load might be divided on more
97
+   machines using the same database.
98
+
99
+   The module can also work only with the functionality of a
100
+   library, with no message processing and generation, but used
101
+   only for the exported functions. This mode of operation is
102
+   enabled if the db_url parameter is not set to any value.
92 103
 
93 104
    The server follows the specifications in: RFC3265, RFC3856,
94 105
    RFC3857, RFC3858.
... ...
@@ -244,6 +255,20 @@ modparam("presence", "server_address", "sip:10.10.10.10:5060")
244 255
 ...
245 256
      _________________________________________________________
246 257
 
258
+1.3.11. fallback2db (int)
259
+
260
+   Setting this parameter enables a fallback to db mode of
261
+   operation. In this mode, in case a searched record is not
262
+   found in cache, the search is continued in database. Useful
263
+   for an architecture in which processing and memory load might
264
+   be divided on more machines using the same database.
265
+
266
+   Example 1-11. Set fallback2db parameter
267
+...
268
+modparam("presence", "fallback2db", 1)
269
+...
270
+     _________________________________________________________
271
+
247 272
 1.4. Exported Functions
248 273
 
249 274
 1.4.1. handle_publish(char* sender_uri)
... ...
@@ -262,7 +287,7 @@ modparam("presence", "server_address", "sip:10.10.10.10:5060")
262 287
 
263 288
    This function can be used from REQUEST_ROUTE.
264 289
 
265
-   Example 1-11. handle_publish usage
290
+   Example 1-12. handle_publish usage
266 291
 ...
267 292
         if(is_method("PUBLISH"))
268 293
         {
... ...
@@ -284,7 +309,7 @@ modparam("presence", "server_address", "sip:10.10.10.10:5060")
284 309
 
285 310
    This function can be used from REQUEST_ROUTE.
286 311
 
287
-   Example 1-12. handle_subscribe usage
312
+   Example 1-13. handle_subscribe usage
288 313
 ...
289 314
 if(method=="SUBSCRIBE")
290 315
     handle_subscribe();
... ...
@@ -38,7 +38,6 @@ int bind_presence(event_api_t* api)
38 38
 	
39 39
 	api->add_event = add_event;
40 40
 	api->contains_event= contains_event;
41
-	api->get_sname_event= get_sname_event;
42 41
 	api->get_event_list= get_event_list;
43 42
 	return 0;
44 43
 }
... ...
@@ -34,7 +34,6 @@
34 34
 typedef struct event_api {
35 35
 	add_event_t add_event;
36 36
 	contains_event_t contains_event;
37
-	get_sname_event_t get_sname_event;
38 37
 	get_event_list_t get_event_list;
39 38
 } event_api_t;
40 39
 
... ...
@@ -20,11 +20,21 @@
20 20
 	module and message-summary from presence_mwi module.
21 21
 	</para>
22 22
 	<para>
23
-	The presence server works with database storage. It stores published information 
24
-	and Subscribe -Notify dialog characteristics.
23
+	The modules uses database storage. 
24
+	It has later been improved with memory caching operations to improve
25
+	performance. The Subscribe dialog information are stored in memory and 
26
+	are periodically updated in database, while for Publish only the presence
27
+	or absence of stored info for a certain resource is maintained in memory
28
+	to avoid unnecessary, costly db operations. 
29
+	It is possible to configure a fallback to database mode(by setting module
30
+	parameter "fallback2db"). In this mode, in case a searched record is not 
31
+	found in cache, the search is continued	in database. This is useful for
32
+	an architecture in which processing and memory load might be divided on 
33
+	more machines using the same database.
25 34
 	</para>
26
-	<para>It can also work only with the functionality of a library, with no message 
27
-	processing and generation, but used only for the exported functions.
35
+	<para>The module can also work only with the functionality of a library,
36
+	with no message processing and generation, but used only for the exported
37
+	functions.
28 38
 	This mode of operation is enabled if the db_url parameter is not set to any value.
29 39
 	</para>
30 40
 	<para>
... ...
@@ -264,6 +274,24 @@ modparam("presence", "server_address", "sip:10.10.10.10:5060")
264 274
 </programlisting>
265 275
 		</example>
266 276
 	</section>
277
+<section>
278
+		<title><varname>fallback2db</varname> (int)</title>
279
+		<para>
280
+		Setting this parameter enables a fallback to db mode of operation.
281
+		In this mode, in case a searched record is not found in cache, 
282
+		the search is continued	in database. Useful for an architecture in
283
+		which processing and memory load might be divided on more machines
284
+		using the same database.
285
+		</para>
286
+		<example>
287
+		<title>Set <varname>fallback2db</varname> parameter</title>
288
+		<programlisting format="linespecific">
289
+...
290
+modparam("presence", "fallback2db", 1)
291
+...
292
+</programlisting>
293
+		</example>
294
+	</section>
267 295
 
268 296
 
269 297
 </section>
... ...
@@ -31,19 +31,93 @@
31 31
 #include <string.h>
32 32
 #include "../../str.h"
33 33
 #include "../../dprint.h"
34
+#include "../../parser/parse_event.h" 
34 35
 #include "../../mem/shm_mem.h" 
36
+#include "../../mem/mem.h" 
35 37
 #include "event_list.h"
38
+#include "hash.h"
36 39
 
37 40
 #define MAX_EVNAME_SIZE 20
38 41
 
39
-int add_event(ev_t* event)
42
+event_t* shm_copy_event(event_t* e)
40 43
 {
41
-	ev_t* ev= NULL;
44
+	event_t* ev= NULL;
45
+	param_t* p1, *p2;
42 46
 	int size;
43
-	char* sep= NULL;
47
+
48
+	ev= (event_t*)shm_malloc(sizeof(event_t));
49
+	if(ev== NULL)
50
+	{
51
+		ERR_MEM("shm_copy_event");
52
+	}
53
+	memset(ev, 0, sizeof(event_t));
54
+
55
+	ev->text.s= (char*)shm_malloc(e->text.len* sizeof(char));
56
+	if(ev->text.s== NULL)
57
+	{
58
+		ERR_MEM("shm_copy_event");
59
+	}
60
+	memcpy(ev->text.s, e->text.s, e->text.len);
61
+	ev->text.len= e->text.len;
62
+
63
+	p1= e->params;
64
+	while(p1)
65
+	{
66
+		size= sizeof(param_t)+ (p1->name.len+ p1->body.len)* sizeof(char);
67
+		p2= (param_t*)shm_malloc(size);
68
+		if(p2== NULL)
69
+		{
70
+			ERR_MEM("shm_copy_event");
71
+		}
72
+		memset(p2, 0, size);
73
+
74
+		size= sizeof(param_t);
75
+		CONT_COPY(p2, p2->name, p1->name);
76
+		if(p1->body.s && p1->body.len)
77
+			CONT_COPY(p2, p2->body, p1->body);
78
+		p2->next= ev->params;
79
+		ev->params= p2;
80
+		p1= p1->next;
81
+	}
82
+	ev->parsed= e->parsed;
83
+
84
+	return ev;
85
+
86
+error:
87
+	shm_free_event(ev);
88
+	return NULL;
89
+}
90
+
91
+void shm_free_event(event_t* ev)
92
+{
93
+	param_t* p1, *p2;
94
+
95
+	if(ev== NULL)
96
+		return;
97
+	
98
+	if(ev->text.s)
99
+		shm_free(ev->text.s);
100
+	p1= ev->params;
101
+	while(p1)
102
+	{
103
+		p2= p1;
104
+		p1= p1->next;
105
+		shm_free(p2);
106
+	}
107
+	shm_free(ev);
108
+}
109
+
110
+
111
+int add_event(pres_ev_t* event)
112
+{
113
+	pres_ev_t* ev= NULL;
114
+	event_t parsed_event;
44 115
 	str wipeer_name;
116
+	char* sep;
45 117
 	char buf[50];
46
-	int ret_code= 1;
118
+	int not_in_list= 0;
119
+
120
+	memset(&parsed_event, 0, sizeof(event_t));
47 121
 
48 122
 	if(event->name.s== NULL || event->name.len== 0)
49 123
 	{
... ...
@@ -56,70 +130,56 @@ int add_event(ev_t* event)
56 130
 		LOG(L_ERR, "PRESENCE: add_event: NULL content_type param\n");
57 131
 		return -1;
58 132
 	}
59
-
60
-	if(contains_event(&event->name, event->param))
61
-	{
62
-		DBG("PRESENCE: add_event: Found prevoius record for event\n");
63
-		ret_code= -1;
64
-		goto done;
65
-	}	
66
-	size= sizeof(ev_t)+ (event->name.len+ event->content_type.len)*sizeof(char);
67
-
68
-	if(event->param)
69
-		size+= sizeof(str)+ ( 2*event->param->len + event->name.len+ 2)* sizeof(char);
70
-
71
-	ev= (ev_t*)shm_malloc(size);
133
+	
134
+	ev= contains_event(&event->name, &parsed_event);
72 135
 	if(ev== NULL)
73 136
 	{
74
-		LOG(L_ERR, "PRESENCE: add_event: ERROR while allocating memory\n");
75
-		ret_code= -1;
76
-		goto done;
77
-	}
78
-	memset(ev, 0, size);
79
-
80
-	size= sizeof(ev_t);
81
-	ev->name.s= (char*)ev+ size;
82
-	ev->name.len= event->name.len;
83
-	memcpy(ev->name.s, event->name.s, event->name.len);
84
-	size+= event->name.len;
137
+		not_in_list= 1;
138
+		ev= (pres_ev_t*)shm_malloc(sizeof(pres_ev_t));
139
+		if(ev== NULL)
140
+		{
141
+			ERR_MEM("add_event");
142
+		}
143
+		memset(ev, 0, sizeof(pres_ev_t));
144
+		ev->name.s= (char*)shm_malloc(event->name.len* sizeof(char));
145
+		if(ev->name.s== NULL)
146
+		{
147
+			ERR_MEM("add_events");
148
+		}
149
+		memcpy(ev->name.s, event->name.s, event->name.len);
150
+		ev->name.len= event->name.len;
85 151
 
86
-	if(event->param)
87
-	{	
88
-		ev->param= (str*)((char*)ev+ size);
89
-		size+= sizeof(str);
90
-		ev->param->s= (char*)ev+ size;
91
-		memcpy(ev->param->s, event->param->s, event->param->len);
92
-		ev->param->len= event->param->len;
93
-		size+= event->param->len;
94
-	
95
-		ev->stored_name.s= (char*)ev+ size;
96
-		memcpy(ev->stored_name.s, event->name.s, event->name.len);
97
-		ev->stored_name.len= event->name.len;
98
-		memcpy(ev->stored_name.s+ ev->stored_name.len, ";", 1);
99
-		ev->stored_name.len+= 1;
100
-		memcpy(ev->stored_name.s+ ev->stored_name.len, event->param->s, event->param->len);
101
-		ev->stored_name.len+= event->param->len;
102
-		size+= ev->stored_name.len;
152
+		ev->evp= shm_copy_event(&parsed_event);
153
+		if(ev->evp== NULL)
154
+		{
155
+			LOG(L_ERR, "PRESENCE:add_event:ERROR copying event_t structure\n");
156
+			goto error;
157
+		}
103 158
 	}
104 159
 	else
105 160
 	{
106
-		ev->stored_name.s= ev->name.s;
107
-		ev->stored_name.len= ev->name.len;
108
-	}	
161
+		if(ev->content_type.s)
162
+		{
163
+			DBG("PRESENCE: add_event: Event already registered\n");
164
+			return 0;
165
+		}
166
+	}
109 167
 
110
-	ev->content_type.s= (char*)ev+ size;
168
+	ev->content_type.s=(char*)shm_malloc(event->content_type.len* sizeof(char)) ;
169
+	if(ev->content_type.s== NULL)
170
+	{
171
+		ERR_MEM("add_event");
172
+	}	
111 173
 	ev->content_type.len= event->content_type.len;
112 174
 	memcpy(ev->content_type.s, event->content_type.s, event->content_type.len);
113
-	size+= ev->content_type.len;
114 175
 
115 176
 	sep= strchr(event->name.s, '.');
116
-
117 177
 	if(sep && strncmp(sep+1, "winfo", 5)== 0)
118 178
 	{	
119 179
 		ev->type= WINFO_TYPE;
120 180
 		wipeer_name.s= event->name.s;
121 181
 		wipeer_name.len= sep - event->name.s;
122
-		ev->wipeer= contains_event(&wipeer_name, ev->param );
182
+		ev->wipeer= contains_event(&wipeer_name, NULL);
123 183
 	}
124 184
 	else
125 185
 	{	
... ...
@@ -129,7 +189,7 @@ int add_event(ev_t* event)
129 189
 		wipeer_name.len= event->name.len;
130 190
 		memcpy(wipeer_name.s+ wipeer_name.len, ".winfo", 6);
131 191
 		wipeer_name.len+= 6;
132
-		ev->wipeer= contains_event(&wipeer_name, ev->param);
192
+		ev->wipeer= contains_event(&wipeer_name, NULL);
133 193
 	}
134 194
 	
135 195
 	if(ev->wipeer)	
... ...
@@ -144,15 +204,36 @@ int add_event(ev_t* event)
144 204
 	ev->free_body= event->free_body;
145 205
 	ev->default_expires= event->default_expires;
146 206
 
147
-	ev->next= EvList->events;
148
-	EvList->events= ev;
207
+	if(not_in_list)
208
+	{
209
+		ev->next= EvList->events;
210
+		EvList->events= ev;
211
+	}
149 212
 	EvList->ev_count++;
150
-
151
-	DBG("PRESENCE: add_event: succesfully added event: %.*s - len= %d\n", 
152
-			ev->stored_name.len, ev->stored_name.s, ev->stored_name.len);
153
-done:
154 213
 	
155
-	return ret_code; 
214
+	DBG("PRESENCE: add_event: succesfully added event: %.*s - len= %d\n", 
215
+			ev->name.len, ev->name.s, ev->name.len);
216
+	return 0;
217
+error:
218
+	if(ev && not_in_list)
219
+	{
220
+		free_pres_event(ev);	
221
+	}
222
+	return -1;
223
+}
224
+
225
+void free_pres_event(pres_ev_t* ev)
226
+{
227
+	if(ev== NULL)
228
+		return;
229
+
230
+	if(ev->name.s)
231
+		shm_free(ev->name.s);
232
+	if(ev->content_type.s)
233
+		shm_free(ev->content_type.s);
234
+	shm_free_event(ev->evp);
235
+	shm_free(ev);
236
+
156 237
 }
157 238
 
158 239
 evlist_t* init_evlist()
... ...
@@ -171,52 +252,74 @@ evlist_t* init_evlist()
171 252
 	return list;
172 253
 }	
173 254
 
174
-ev_t* contains_event(str* name, str* param)
255
+pres_ev_t* contains_event(str* sname, event_t* parsed_event)
175 256
 {
176
-	ev_t* event;
177
-	event= EvList->events;
257
+	event_t event;
258
+	pres_ev_t* e;
178 259
 
179
-	while(event)
260
+	if(event_parser(sname->s, sname->len, &event)< 0)
180 261
 	{
181
-		if(event->name.len== name->len &&
182
-				strncmp(event->name.s, name->s, name->len)== 0)
183
-		{
184
-			// verify if there is a restrictive params and if it equals the given one
185
-			if(!event->param)
186
-				return event;
187
-			
188
-			if(!param)
189
-				return NULL;
190
-
191
-			if(event->param->len== param->len &&
192
-					strncmp(event->param->s, param->s, param->len)== 0)
193
-				return event;
262
+		LOG(L_ERR, "PRESENCE:contains_event: ERROR parsing event\n");
263
+		return NULL;
264
+	}
265
+	if(parsed_event)
266
+		*parsed_event= event;
194 267
 	
195
-		}
196
-		
197
-		event= event->next;
198
-	}	
268
+	e= search_event(&event);
199 269
 
200
-	return NULL;	
270
+	return e;
201 271
 }
272
+	
202 273
 
203
-ev_t* get_sname_event(str* stored_name)
274
+pres_ev_t* search_event(event_t* event)
204 275
 {
205
-	ev_t* event;
206
-	event= EvList->events;
276
+	pres_ev_t* pres_ev;
277
+	pres_ev= EvList->events;
278
+	param_t* ps, *p;
279
+	int found;
207 280
 
208
-	while(event)
281
+	DBG("PRESENCE:search_event...\n");
282
+	while(pres_ev)
209 283
 	{
210
-		if(stored_name->len== event->stored_name.len && 
211
-			strncmp(stored_name->s,event->stored_name.s,stored_name->len)==0)
212
-			return event;
213
-		event= event->next;
284
+		if(pres_ev->evp->parsed== event->parsed)
285
+		{
286
+			if(event->params== NULL)
287
+				return pres_ev;
288
+	
289
+			/* search all parameters in event in ev */
290
+			ps= event->params;
291
+			while(ps)
292
+			{
293
+				p= pres_ev->evp->params;
294
+				found= 0;
295
+				while(p)
296
+				{
297
+					if(p->name.len== ps->name.len && 
298
+					strncmp(p->name.s,ps->name.s, ps->name.len)== 0)
299
+						if((p->body.s== 0 && ps->body.s== 0) ||
300
+						(p->body.len== ps->body.len && 
301
+						 strncmp(p->body.s,ps->body.s,ps->body.len)== 0))
302
+						{
303
+							found= 1;
304
+							break;
305
+						}
306
+					p= p->next;
307
+				}
308
+				if(found== 0)
309
+					return NULL;
310
+				ps= ps->next;
311
+			}
312
+			return pres_ev;
313
+		}
314
+		pres_ev= pres_ev->next;
214 315
 	}
215 316
 	return NULL;
317
+
216 318
 }
319
+
217 320
 int get_event_list(str** ev_list)
218 321
 {	
219
-	ev_t* ev= EvList->events;
322
+	pres_ev_t* ev= EvList->events;
220 323
 	int i;
221 324
 	str* list;
222 325
 	*ev_list= NULL;
... ...
@@ -247,8 +350,8 @@ int get_event_list(str** ev_list)
247 350
 			memcpy(list->s+ list->len, ", ", 2);
248 351
 			list->len+= 2;
249 352
 		}	
250
-		memcpy(list->s+ list->len, ev->stored_name.s, ev->stored_name.len );
251
-		list->len+= ev->stored_name.len ;
353
+		memcpy(list->s+ list->len, ev->name.s, ev->name.len );
354
+		list->len+= ev->name.len ;
252 355
 		ev= ev->next;
253 356
 	}
254 357
 	
... ...
@@ -258,14 +361,14 @@ int get_event_list(str** ev_list)
258 361
 
259 362
 void destroy_evlist()
260 363
 {
261
-    ev_t* e1, *e2;
364
+    pres_ev_t* e1, *e2;
262 365
     if (EvList) 
263 366
 	{
264 367
 		e1= EvList->events;
265 368
 		while(e1)
266 369
 	    {
267 370
 			e2= e1->next;
268
-			shm_free(e1);
371
+			free_pres_event(e1);
269 372
 			e1= e2;
270 373
 	    }	
271 374
 		shm_free(EvList);
... ...
@@ -30,6 +30,7 @@
30 30
 #define  _PRES_EV_LST_H
31 31
 
32 32
 #include "../../parser/msg_parser.h"
33
+#include "../../parser/parse_event.h"
33 34
 #include "../../str.h"
34 35
 #include "subscribe.h"
35 36
 
... ...
@@ -61,12 +62,10 @@ typedef int (is_allowed_t)(struct subscription* subs);
61 62
 /* event specific body free function */
62 63
 typedef void(free_body_t)(char* body);
63 64
 
64
-struct ev
65
+struct pres_ev
65 66
 {
66 67
 	str name;
67
-	str* param;         // required param 
68
-	/* to do: transform it in a list ( for multimple param)*/
69
-	str stored_name;
68
+	event_t* evp;
70 69
 	str content_type;
71 70
 	int default_expires;
72 71
 	int type;
... ...
@@ -94,31 +93,27 @@ struct ev
94 93
 	publ_handling_t  * evs_publ_handl;
95 94
 	subs_handling_t  * evs_subs_handl;
96 95
 	free_body_t* free_body;
97
-	struct ev* wipeer;			
98
-	struct ev* next;
96
+	struct pres_ev* wipeer;			
97
+	struct pres_ev* next;
99 98
 	
100 99
 };
101
-typedef struct ev ev_t;
100
+typedef struct pres_ev pres_ev_t;
102 101
 
103 102
 typedef struct evlist
104 103
 {
105 104
 	int ev_count;
106
-	ev_t* events;
105
+	pres_ev_t* events;
107 106
 }evlist_t;	
108 107
 
109 108
 evlist_t* init_evlist();
110 109
 
111
-int add_event(ev_t* event);
110
+int add_event(pres_ev_t* event);
112 111
 
113
-typedef int (*add_event_t)(ev_t* event);
112
+typedef int (*add_event_t)(pres_ev_t* event);
114 113
 
115
-ev_t* contains_event(str* name, str* param);
114
+pres_ev_t* contains_event(str* name, event_t* parsed_event);
116 115
 
117
-typedef ev_t* (*contains_event_t) (str* name, str* param);
118
-
119
-ev_t* get_sname_event(str* stored_name);
120
-
121
-typedef ev_t* (*get_sname_event_t)(str* stored_name);
116
+typedef pres_ev_t* (*contains_event_t)(str* name, event_t* parsed_event);
122 117
 
123 118
 int get_event_list(str** ev_list);
124 119
 
... ...
@@ -128,4 +123,13 @@ void destroy_evlist();
128 123
 
129 124
 extern evlist_t* EvList;
130 125
 
126
+pres_ev_t* search_event(event_t* event);
127
+
128
+event_t* shm_copy_event(event_t* e);
129
+
130
+void shm_free_event(event_t* ev);
131
+
132
+void free_pres_event(pres_ev_t* ev);
133
+
134
+
131 135
 #endif
... ...
@@ -38,8 +38,9 @@
38 38
 #include "../../str.h"
39 39
 #include "../../db/db.h"
40 40
 #include "../../db/db_val.h"
41
-#include "../tm/tm_load.h"
42 41
 #include "../../socket_info.h"
42
+#include "../tm/tm_load.h"
43
+#include "../pua/hash.h"
43 44
 #include "presentity.h"
44 45
 #include "presence.h"
45 46
 #include "notify.h"
... ...
@@ -49,38 +50,47 @@
49 50
 #define MAX_FORWARD 70
50 51
 
51 52
 extern struct tm_binds tmb;
52
-c_back_param* shm_dup_subs(subs_t* subs, str to_tag);
53
+c_back_param* shm_dup_cbparam(subs_t* , subs_t*);
54
+void free_cbparam(c_back_param* cb_param);
53 55
 
54 56
 void p_tm_callback( struct cell *t, int type, struct tmcb_params *ps);
55 57
 
58
+char* get_status_str(int status_flag)
59
+{
60
+	switch(status_flag)
61
+	{
62
+		case ACTIVE_STATUS: return "active";
63
+		case PENDING_STATUS: return "pending";
64
+		case TERMINATED_STATUS: return "terminated";
65
+	}
66
+	return NULL;
67
+}
68
+
56 69
 void printf_subs(subs_t* subs)
57 70
 {	
58
-	DBG("\n\tpres_user= %.*s - len: %d\tpres_domain= %.*s - len: %d", 
59
-			subs->pres_user.len,  subs->pres_user.s, subs->pres_user.len,
60
-			subs->pres_domain.len,  subs->pres_domain.s, subs->pres_domain.len);
61
-	DBG("\n\t[p_user]= %.*s  [p_domain]= %.*s\n\t[w_user]= %.*s "  
62
-			"[w_domain]= %.*s\n",
63
-			subs->to_user.len, subs->to_user.s, subs->to_domain.len,
64
-			subs->to_domain.s,
65
-			subs->from_user.len, subs->from_user.s, subs->from_domain.len,
66
-			subs->from_domain.s);
67
-	DBG("[event]= %.*s\n\t[status]= %.*s\n\t[expires]= %d\n",
68
-			subs->event->stored_name.len, subs->event->stored_name.s,	subs->status.len, subs->status.s,
69
-			subs->expires );
70
-	DBG("[to_tag]= %.*s\n\t[from_tag]= %.*s\n",
71
-			subs->to_tag.len, subs->to_tag.s,	subs->from_tag.len, subs->from_tag.s);
72
-	DBG("[contact]= %.*s\n",
73
-			subs->contact.len, subs->contact.s);
71
+	DBG("\t[pres_uri]= %.*s - len: %d", 
72
+		subs->pres_uri.len,  subs->pres_uri.s, subs->pres_uri.len);
73
+	DBG("\n\t[to_user]= %.*s\t[to_domain]= %.*s\n\t[w_user]= %.*s"
74
+		"\t[w_domain]= %.*s",subs->to_user.len,subs->to_user.s, 
75
+		subs->to_domain.len,subs->to_domain.s,subs->from_user.len,
76
+		subs->from_user.s, subs->from_domain.len,subs->from_domain.s);
77
+	DBG("\n\t[event]= %.*s\n\t[status]= %s\n\t[expires]= %u",
78
+		subs->event->name.len, subs->event->name.s,	
79
+		get_status_str(subs->status), subs->expires );
80
+	DBG("\n\t[to_tag]= %.*s\n\t[from_tag]= %.*s",subs->to_tag.len, 
81
+		subs->to_tag.s,	subs->from_tag.len, subs->from_tag.s);
82
+	DBG("\n\t[contact]= %.*s\n",subs->contact.len, subs->contact.s);
74 83
 }
75
-str* create_winfo_xml(watcher_t* watchers,int n, char* version,char* resource, int STATE_FLAG );
84
+str* create_winfo_xml(watcher_t* watchers, char* version,str resource, int STATE_FLAG );
76 85
 
77 86
 int build_str_hdr(subs_t* subs, int is_body, str** hdr)
78 87
 {
79 88
 	str* str_hdr = NULL;	
80 89
 	char* subs_expires = NULL;
81 90
 	int len = 0;
82
-	ev_t* event= subs->event;
91
+	pres_ev_t* event= subs->event;
83 92
 	int expires_t;
93
+	char* status= NULL;
84 94
 
85 95
 	str_hdr =(str*)pkg_malloc(sizeof(str));
86 96
 	if(str_hdr== NULL)
... ...
@@ -114,9 +124,9 @@ int build_str_hdr(subs_t* subs, int is_body, str** hdr)
114 124
 
115 125
 	strncpy(str_hdr->s+str_hdr->len  ,"Event: ", 7);
116 126
 	str_hdr->len+= 7;
117
-	strncpy(str_hdr->s+str_hdr->len, event->stored_name.s, event->stored_name.len);
118
-	str_hdr->len+= event->stored_name.len;
119
-	if (subs->event_id.len) 
127
+	strncpy(str_hdr->s+str_hdr->len, event->name.s, event->name.len);
128
+	str_hdr->len+= event->name.len;
129
+	if(subs->event_id.len && subs->event_id.s) 
120 130
 	{
121 131
  		strncpy(str_hdr->s+str_hdr->len, ";id=", 4);
122 132
  		str_hdr->len += 4;
... ...
@@ -126,7 +136,6 @@ int build_str_hdr(subs_t* subs, int is_body, str** hdr)
126 136
 	strncpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
127 137
 	str_hdr->len += CRLF_LEN;
128 138
 
129
-
130 139
 	strncpy(str_hdr->s+str_hdr->len ,"Contact: <", 10);
131 140
 	str_hdr->len += 10;
132 141
 	strncpy(str_hdr->s+str_hdr->len, subs->local_contact.s, subs->local_contact.len);
... ...
@@ -135,15 +144,34 @@ int build_str_hdr(subs_t* subs, int is_body, str** hdr)
135 144
 	str_hdr->len += 1;
136 145
 	strncpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
137 146
 	str_hdr->len += CRLF_LEN;
138
-
139
-	if(strncmp(subs->status.s, "terminated",10) == 0)
147
+	
148
+	strncpy(str_hdr->s+str_hdr->len,"Subscription-State: ", 20);
149
+	str_hdr->len+= 20;
150
+	status= get_status_str(subs->status);
151
+	if(status== NULL)
152
+	{
153
+		LOG(L_ERR,"PRESENCE: build_str_hdr: ERROR bad status flag= %d\n",
154
+				subs->status);
155
+		pkg_free(str_hdr->s);
156
+		pkg_free(str_hdr);
157
+		return -1;
158
+	}
159
+	strcpy(str_hdr->s+str_hdr->len, status);
160
+	str_hdr->len+= strlen(status);
161
+	
162
+	if(subs->expires <= 0)
163
+	{
164
+		expires_t = 0;
165
+		subs->status= TERMINATED_STATUS;
166
+		subs->reason.s= "timeout";
167
+		subs->reason.len= 7;
168
+	}
169
+	else
170
+		expires_t= subs->expires;
171
+	
172
+	if(subs->status== TERMINATED_STATUS)
140 173
 	{
141 174
 		DBG( "PRESENCE: build_str_hdr: state = terminated \n");
142
-
143
-		strncpy(str_hdr->s+str_hdr->len,"Subscription-State: ", 20);
144
-		str_hdr->len+= 20;
145
-		strncpy(str_hdr->s+str_hdr->len, subs->status.s ,subs->status.len );
146
-		str_hdr->len+= subs->status.len;
147 175
 		
148 176
 		strncpy(str_hdr->s+str_hdr->len,";reason=", 8);
149 177
 		str_hdr->len+= 8;
... ...
@@ -151,22 +179,12 @@ int build_str_hdr(subs_t* subs, int is_body, str** hdr)
151 179
 		str_hdr->len+= subs->reason.len;
152 180
 		strncpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
153 181
 		str_hdr->len+= CRLF_LEN;
154
-
155 182
 	}
156 183
 	else
157 184
 	{	
158
-		strncpy(str_hdr->s+str_hdr->len,"Subscription-State: ", 20);
159
-		str_hdr->len += 20;
160
-		strncpy(str_hdr->s+str_hdr->len, subs->status.s ,subs->status.len );
161
-		str_hdr->len += subs->status.len;
162 185
 		strncpy(str_hdr->s+str_hdr->len,";expires=", 9);
163 186
 		str_hdr->len+= 9;
164 187
 	
165
-		if(subs->expires < 0)
166
-			expires_t = 0;
167
-		else
168
-			expires_t= subs->expires;
169
-
170 188
 		subs_expires= int2str(expires_t, &len); 
171 189
 
172 190
 		if(subs_expires == NULL || len == 0)
... ...
@@ -196,7 +214,14 @@ int build_str_hdr(subs_t* subs, int is_body, str** hdr)
196 214
 			str_hdr->len += CRLF_LEN;
197 215
 		}
198 216
 	}
217
+	if(str_hdr->len> ALLOC_SIZE)
218
+	{
219
+		LOG(L_ERR, "PRESENCE:build_str_hdr:ERROR buffer size overflown\n");
220
+		pkg_free(str_hdr->s);
221
+		pkg_free(str_hdr);
222
+		return -1;
199 223
 
224
+	}
200 225
 	str_hdr->s[str_hdr->len] = '\0';
201 226
 	*hdr= str_hdr;
202 227
 
... ...
@@ -204,8 +229,9 @@ int build_str_hdr(subs_t* subs, int is_body, str** hdr)
204 229
 
205 230
 }
206 231
 
207
-str* get_wi_notify_body(subs_t* subs, subs_t* watcher_subs)
208
-{
232
+int get_wi_subs_db(subs_t* subs, watcher_t** watchers)
233
+{	
234
+	watcher_t *w;
209 235
 	db_key_t query_cols[6];
210 236
 	db_op_t  query_ops[6];
211 237
 	db_val_t query_vals[6];
... ...
@@ -213,209 +239,293 @@ str* get_wi_notify_body(subs_t* subs, subs_t* watcher_subs)
213 239
 	db_res_t *result = NULL;
214 240
 	db_row_t *row = NULL ;	
215 241
 	db_val_t *row_vals = NULL;
216
-	str* notify_body = NULL;
217
-	str p_uri;
218
-	char* version_str;
219
-	watcher_t *watchers = NULL;
220
-	watcher_t swatchers;
221 242
 	int n_result_cols = 0;
222 243
 	int n_query_cols = 0;
223
-	int i , len = 0;
244
+	int i;
224 245
 	int status_col, expires_col, from_user_col, from_domain_col;
225
-	
226
-	uandd_to_uri(subs->to_user, subs->to_domain, &p_uri);
227
-	if(p_uri.s == NULL)
228
-	{
229
-		LOG(L_ERR,"PRESENCE:get_wi_notify_body: ERROR while creating uri\n");
230
-		return NULL;
231
-	}
232
-
233
-	memset(&swatchers, 0, sizeof(watcher_t));
234
-	version_str = int2str(subs->version, &len);
235
-
236
-	if(version_str ==NULL)
237
-	{
238
-		LOG(L_ERR,"PRESENCE:get_wi_notify_body: ERROR while converting int"
239
-				" to str\n ");
240
-		goto error;
241
-	}
242
-
243
-	if(watcher_subs != NULL) /*no need to query data base */
244
-	{
245
-		
246
-		swatchers.status= watcher_subs->status;
247
-		uandd_to_uri( watcher_subs->from_user,watcher_subs->from_domain,
248
-						&swatchers.uri);
249
-		if(swatchers.uri.s== NULL)
250
-			goto error;
251
-
252
-		swatchers.id.s = (char *)pkg_malloc(swatchers.uri.len *2 +1);
253
-		if(swatchers.id.s==0)
254
-		{
255
-			LOG(L_ERR,"PRESENCE:get_wi_notify_body: ERROR no more pkg mem\n");
256
-			pkg_free(swatchers.uri.s);
257
-			goto error;
258
-		}
259
-		to64frombits((unsigned char *)swatchers.id.s,
260
-				(const unsigned char*) swatchers.uri.s, swatchers.uri.len );
261
-			
262
-		swatchers.id.len = strlen(swatchers.id.s);
263
-		
264
-		swatchers.event= watcher_subs->event->stored_name;
265
-		
266
-		notify_body = create_winfo_xml(&swatchers, 1, version_str,p_uri.s,
267
-				PARTIAL_STATE_FLAG );
268
-
269
-		if(swatchers.uri.s !=NULL)
270
-			pkg_free(swatchers.uri.s );
271
-		if(swatchers.id.s !=NULL)
272
-			pkg_free(swatchers.id.s );
273
-
274
-		pkg_free(p_uri.s);			
275
-		return notify_body;
276
-	}
277
-
278
-	query_cols[n_query_cols] = "pres_user";
279
-	query_ops[n_query_cols] = OP_EQ;
280
-	query_vals[n_query_cols].type = DB_STR;
281
-	query_vals[n_query_cols].nul = 0;
282
-	query_vals[n_query_cols].val.str_val= subs->pres_user;
283
-	n_query_cols++;
246
+	str from_user, from_domain;
284 247
 
285
-	query_cols[n_query_cols] = "pres_domain";
248
+	query_cols[n_query_cols] = "pres_uri";
286 249
 	query_ops[n_query_cols] = OP_EQ;
287 250
 	query_vals[n_query_cols].type = DB_STR;
288 251
 	query_vals[n_query_cols].nul = 0;
289
-	query_vals[n_query_cols].val.str_val = subs->pres_domain;
252
+	query_vals[n_query_cols].val.str_val= subs->pres_uri;
290 253
 	n_query_cols++;
291 254
 
292
-	
293 255
 	query_cols[n_query_cols] = "event";
294 256
 	query_ops[n_query_cols] = OP_EQ;
295 257
 	query_vals[n_query_cols].type = DB_STR;
296 258
 	query_vals[n_query_cols].nul = 0;
297
-	query_vals[n_query_cols].val.str_val = subs->event->wipeer->stored_name;
259
+	query_vals[n_query_cols].val.str_val = subs->event->wipeer->name;
298 260
 	n_query_cols++;
299 261
 
300 262
 	result_cols[status_col=n_result_cols++] = "status" ;
301 263
 	result_cols[expires_col=n_result_cols++] = "expires";
302 264
 	result_cols[from_user_col=n_result_cols++] = "from_user";
303 265
 	result_cols[from_domain_col=n_result_cols++] = "from_domain";
304
-
305 266
 	
306 267
 	if (pa_dbf.use_table(pa_db, active_watchers_table) < 0) 
307 268
 	{
308
-		LOG(L_ERR, "PRESENCE:get_wi_notify_body: Error in use_table\n");
269
+		LOG(L_ERR, "PRESENCE:get_wi_subs_db: Error in use_table\n");
309 270
 		goto error;
310 271
 	}
311 272
 
312
-	DBG("PRESENCE:get_wi_notify_body: querying database  \n");
313 273
 	if (pa_dbf.query (pa_db, query_cols, query_ops, query_vals,
314 274
 		 result_cols, n_query_cols, n_result_cols, 0,  &result) < 0) 
315 275
 	{
316
-		LOG(L_ERR, "PRESENCE:get_wi_notify_body: Error while querying"
317
-				" presentity\n");
276
+		LOG(L_ERR, "PRESENCE:get_wi_subs_db: Error while querying"
277
+				" watchers\n");
318 278
 		goto error;
319 279
 	}
320 280
 
321
-	if (result== NULL )
281
+	if(result== NULL )
322 282
 	{
323
-		LOG(L_ERR, "PRESENCE: get_wi_notify_body:The query returned no"
283
+		LOG(L_ERR, "PRESENCE: get_wi_subs_db:The query returned no"
324 284
 				" result\n");
325 285
 		goto error;
326 286
 	}
327
-	else
328
-	if(result->n >0)			
287
+
288
+	if(result->n <= 0)
289
+	{
290
+		DBG("PRESENCEget_wi_subs_db:The query in databse returned no result\n");
291
+		pa_dbf.free_result(pa_db, result);
292
+		return 0;
293
+	}
294
+	
295
+	for(i=0; i<result->n; i++)
329 296
 	{
330
-		str from_user;
331
-		str from_domain;
297
+		row = &result->rows[i];
298
+		row_vals = ROW_VALUES(row);
299
+		
300
+		from_user.s= (char*)row_vals[from_user_col].val.string_val;
301
+		from_user.len= strlen(from_user.s);
332 302
 
333
-		watchers =(watcher_t*)pkg_malloc( (result->n+1)*sizeof(watcher_t));
334
-		if(watchers == NULL)
303
+		from_domain.s= (char*)row_vals[from_domain_col].val.string_val;
304
+		from_domain.len= strlen(from_domain.s);
305
+
306
+		w= (watcher_t*)pkg_malloc(sizeof(watcher_t));
307
+		if(w== NULL)
335 308
 		{
336
-			LOG(L_ERR, "PRESENCE:get_wi_notify_body:ERROR while allocating"
337
-					" memory\n");
309
+			ERR_MEM("get_wi_subs_db");
310
+		}
311
+		w->status= row_vals[status_col].val.int_val;
312
+		if(uandd_to_uri(from_user, from_domain, &w->uri)<0)
313
+	 	{
314
+			pkg_free(w);
315
+   			LOG(L_ERR, "PRESENCE:get_wi_subs_db:ERROR while creating"
316
+   				" uri\n");
317
+   			goto error;
318
+   		}
319
+		w->id.s = (char*)pkg_malloc(w->uri.len*2 +1);
320
+		if(w->id.s== NULL)
321
+		{
322
+			LOG(L_ERR,"PRESENCE:get_wi_notify_body: ERROR no more pkg mem\n");
323
+			pkg_free(w->uri.s);
324
+			pkg_free(w);
338 325
 			goto error;
339 326
 		}
340
-		memset(watchers, 0, (result->n+1)*sizeof(watcher_t));
341 327
 
342
-		for(i=0; i<result->n; i++)
343
-		{
344
-			row = &result->rows[i];
345
-			row_vals = ROW_VALUES(row);
346
-			watchers[i].status.s = (char*)row_vals[status_col].val.string_val;
347
-			watchers[i].status.len= strlen(watchers[i].status.s);
328
+		to64frombits((unsigned char *)w->id.s,
329
+   			(const unsigned char*)w->uri.s, w->uri.len);
330
+   
331
+   		w->id.len = strlen(w->id.s);
332
+  		w->event= subs->event->wipeer->name;
333
+		
334
+		w->next= (*watchers)->next;
335
+		(*watchers)->next= w;
336
+	}
337
+	
338
+	pa_dbf.free_result(pa_db, result);
339
+	return 0;
348 340
 
349
-			from_user.s= (char*)row_vals[from_user_col].val.string_val;
350
-			from_user.len= strlen(from_user.s);
341
+error:
342
+	if(result)
343
+		pa_dbf.free_result(pa_db, result);
344
+	return -1;
345
+}
351 346
 
352
-			from_domain.s= (char*)row_vals[from_domain_col].val.string_val;
353
-			from_domain.len= strlen(from_domain.s);
347
+str* get_wi_notify_body(subs_t* subs, subs_t* watcher_subs)
348
+{
349
+	str* notify_body = NULL;
350
+	char* version_str;
351
+	watcher_t *watchers = NULL, *w= NULL;
352
+	int len = 0;
353
+	unsigned int hash_code;
354
+	subs_t* s= NULL;
354 355
 
355
-			if(uandd_to_uri(from_user, from_domain, &watchers[i].uri)<0)
356
-			{
357
-				LOG(L_ERR, "PRESENCE:get_wi_notify_body:ERROR while creating"
358
-					" uri\n");
359
-				goto error;
360
-			}	
361
-			watchers[i].id.s = (char*)pkg_malloc(watchers[i].uri.len*2 +1);
362
-			to64frombits((unsigned char *)watchers[i].id.s,
363
-					(const unsigned char*) watchers[i].uri.s,watchers[i].uri.len );
356
+	version_str = int2str(subs->version, &len);
357
+	if(version_str ==NULL)
358
+	{
359
+		LOG(L_ERR,"PRESENCE:get_wi_notify_body: ERROR while converting int"
360
+				" to str\n ");
361
+		goto error;
362
+	}
363
+
364
+	watchers= (watcher_t*)pkg_malloc(sizeof(watcher_t));
365
+	if(watchers== NULL)
366
+	{
367
+		ERR_MEM("get_wi_notify_body");
368
+	}
369
+	memset(watchers, 0, sizeof(watcher_t));
370
+
371
+	if(watcher_subs != NULL) 
372
+	{		
373
+		w= (watcher_t *)pkg_malloc(sizeof(watcher_t));
374
+		if(w== NULL)
375
+		{
376
+			ERR_MEM("get_wi_notify_body");
377
+		}
378
+		memset(w, 0, sizeof(watcher_t));
379
+
380
+		w->status= watcher_subs->status;
381
+		uandd_to_uri( watcher_subs->from_user,watcher_subs->from_domain,
382
+						&w->uri);
383
+		if(w->uri.s== NULL)
384
+		{
385
+			pkg_free(w);
386
+			goto error;
387
+		}
388
+
389
+		w->id.s = (char *)pkg_malloc(w->uri.len *2 +1);
390
+		if(w->id.s== NULL)
391
+		{
392
+			pkg_free(w->uri.s);
393
+			pkg_free(w);
394
+			ERR_MEM("get_wi_notify_body");
395
+		}
396
+		to64frombits((unsigned char *)w->id.s,
397
+				(const unsigned char*)w->uri.s, w->uri.len );
364 398
 			
365
-			watchers[i].id.len = strlen(watchers[i].id.s);
366
-			watchers[i].event= subs->event->wipeer->stored_name;
399
+		w->id.len = strlen(w->id.s);
400
+		
401
+		w->event= watcher_subs->event->name;
402
+		
403
+		w->next= watchers->next;
404
+		watchers->next= w;
405
+
406
+		goto done;
407
+	}
408
+
409
+	if(fallback2db)
410
+	{
411
+		if(get_wi_subs_db(subs, &watchers)< 0)
412
+		{
413
+			LOG(L_ERR, "PRESENCE:get_wi_notify_body: ERROR getting watchers"
414
+					"from database\n");
415
+			goto error;
367 416
 		}
368 417
 	}
369 418
 
370
-	DBG( "PRESENCE:get_wi_notify_body: the query returned no result\n");
371
-	notify_body = create_winfo_xml(watchers, result->n, version_str, p_uri.s,
372
-			FULL_STATE_FLAG );
419
+	hash_code= core_hash(&subs->pres_uri, &subs->event->name, shtable_size);
420
+	DBG("PRESENCE:get_wi_notify_body:hash_code= %u\n", hash_code);
421
+	lock_get(&subs_htable[hash_code].lock);
422
+
423
+	s= subs_htable[hash_code].entries;
373 424
 
374
-	if(watchers!=NULL) 
425
+	while(s->next)
375 426
 	{
376
-		for(i = 0; i<result->n; i++)
427
+		s= s->next;
428
+
429
+		if(s->expires< (int)time(NULL))
430
+		{	
431
+			DBG("PRESENCE:get_wi_notify_body:expired record\n");
432
+			continue;
433
+		}
434
+
435
+		if(fallback2db && s->db_flag!= INSERTDB_FLAG)
377 436
 		{
378
-			if(watchers[i].uri.s !=NULL)
379
-				pkg_free(watchers[i].uri.s );
380
-			if(watchers[i].id.s !=NULL)
381
-				pkg_free(watchers[i].id.s );
437
+			DBG("PRESENCE:get_wi_notify_body:record already taken"
438
+					" from database\n");
439
+			continue;
440
+		}
441
+
442
+		if(s->event== subs->event->wipeer && 
443
+			s->pres_uri.len== subs->pres_uri.len &&
444
+			strncmp(s->pres_uri.s, subs->pres_uri.s,subs->pres_uri.len)== 0)
445
+		{
446
+			w= (watcher_t*)pkg_malloc(sizeof(watcher_t));
447
+			if(w== NULL)
448
+			{
449
+				lock_release(&subs_htable[hash_code].lock);
450
+				ERR_MEM("get_wi_notify_body");
451
+			}
452
+			w->status= s->status;
453
+			if(uandd_to_uri(s->from_user, s->from_domain, &w->uri)<0)
454
+	 		{
455
+				lock_release(&subs_htable[hash_code].lock);
456
+				pkg_free(w);
457
+   				LOG(L_ERR, "PRESENCE:get_wi_notify_body:ERROR while creating"
458
+   					" uri\n");
459
+   				goto error;
460
+   			}
461
+			w->id.s = (char*)pkg_malloc(w->uri.len*2 +1);
462
+			if(w->id.s== NULL)
463
+			{
464
+				LOG(L_ERR,"PRESENCE:get_wi_notify_body: ERROR no more pkg mem\n");
465
+				lock_release(&subs_htable[hash_code].lock);
466
+				pkg_free(w->uri.s);
467
+				pkg_free(w);
468
+				goto error;
469
+			}
470
+
471
+			to64frombits((unsigned char *)w->id.s,
472
+   				(const unsigned char*)w->uri.s, w->uri.len);
473
+   
474
+   			w->id.len = strlen(w->id.s);
475
+  			w->event= subs->event->wipeer->name;
476
+		
477
+			w->next= watchers->next;
478
+			watchers->next= w;
382 479
 		}
383
-		pkg_free(watchers);
384 480
 	}
385
-	pa_dbf.free_result(pa_db, result);
386
-	if(p_uri.s)
387
-		pkg_free(p_uri.s);
481
+	
482
+done:
483
+	notify_body = create_winfo_xml(watchers,version_str,subs->pres_uri,
484
+			FULL_STATE_FLAG );
485
+	
486
+	if(watcher_subs == NULL) 
487
+		lock_release(&subs_htable[hash_code].lock);
388 488
 
489
+	if(notify_body== NULL)
490
+	{
491
+		LOG(L_ERR, "PRESENCE: get_wi_notify_body: Error in function"
492
+				" create_winfo_xml\n");
493
+		goto error;
494
+	}
495
+	while(watchers)
496
+	{	
497
+		w= watchers;
498
+		if(w->uri.s !=NULL)
499
+			pkg_free(w->uri.s);
500
+		if(w->id.s !=NULL)
501
+			pkg_free(w->id.s);
502
+		watchers= watchers->next;
503
+		pkg_free(w);
504
+	}
389 505
 	return notify_body;
390 506
 
391 507
 error:
392
-	if(result!=NULL)
393
-		pa_dbf.free_result(pa_db, result);
394
-
395 508
 	if(notify_body)
396 509
 	{
397 510
 		if(notify_body->s)
398 511
 			xmlFree(notify_body->s);
399 512
 		pkg_free(notify_body);
400 513
 	}
401
-	if(watchers!=NULL) 
402
-	{
403
-		for(i = 0; i<result->n; i++)
404
-		{
405
-			if(watchers[i].uri.s !=NULL)
406
-				pkg_free(watchers[i].uri.s );
407
-			if(watchers[i].id.s !=NULL)
408
-				pkg_free(watchers[i].id.s );
409
-		}
410
-		pkg_free(watchers);
514
+	while(watchers)
515
+	{	
516
+		w= watchers;
517
+		if(w->uri.s !=NULL)
518
+			pkg_free(w->uri.s);
519
+		if(w->id.s !=NULL)
520
+			pkg_free(w->id.s);
521
+		watchers= watchers->next;
522
+		pkg_free(w);
411 523
 	}
412
-	if(p_uri.s)
413
-		pkg_free(p_uri.s);
414 524
 
415 525
 	return NULL;
416
-
417 526
 }
418
-str* get_p_notify_body(str user, str host, ev_t* event, str* etag)
527
+
528
+str* get_p_notify_body(str pres_uri, pres_ev_t* event, str* etag)
419 529
 {
420 530
 	db_key_t query_cols[6];
421 531
 	db_val_t query_vals[6];
... ...
@@ -433,23 +543,51 @@ str* get_p_notify_body(str user, str host, ev_t* event, str* etag)
433 543
 	str etags;
434 544
 	str* body;
435 545
 	int size= 0;
546
+	struct sip_uri uri;
547
+	unsigned int hash_code;
548
+
549
+	if(parse_uri(pres_uri.s, pres_uri.len, &uri)< 0)
550
+	{
551
+		LOG(L_ERR, "PRESENCE: get_p_notify_body: ERROR while parsing uri\n");
552
+		return NULL;
553
+	}
554
+
555
+	/* search in hash table if any record exists */
556
+	hash_code= core_hash(&pres_uri, NULL, phtable_size);
557
+	if(search_phtable(&pres_uri, event->evp->parsed, hash_code)== NULL)
558
+	{
559
+		DBG("PRESENCE: get_p_notify_body: No record exists in hash_table\n");
560
+		if(fallback2db)
561
+			goto db_query;
562
+
563
+		/* for pidf manipulation */
564
+		if(event->agg_nbody)
565
+		{
566
+			notify_body = event->agg_nbody(&uri.user, &uri.host, NULL, 0, -1);
567
+			if(notify_body)
568
+				goto done;
569
+		}			
570
+		return NULL;
571
+	}
572
+
573
+db_query:
436 574
 
437 575
 	query_cols[n_query_cols] = "domain";
438 576
 	query_vals[n_query_cols].type = DB_STR;
439 577
 	query_vals[n_query_cols].nul = 0;
440
-	query_vals[n_query_cols].val.str_val = host;
578
+	query_vals[n_query_cols].val.str_val = uri.host;
441 579
 	n_query_cols++;
442 580
 
443 581
 	query_cols[n_query_cols] = "username";
444 582
 	query_vals[n_query_cols].type = DB_STR;
445 583
 	query_vals[n_query_cols].nul = 0;
446
-	query_vals[n_query_cols].val.str_val = user;
584
+	query_vals[n_query_cols].val.str_val = uri.user;
447 585
 	n_query_cols++;
448 586
 
449 587
 	query_cols[n_query_cols] = "event";
450 588
 	query_vals[n_query_cols].type = DB_STR;
451 589
 	query_vals[n_query_cols].nul = 0;
452
-	query_vals[n_query_cols].val.str_val= event->stored_name;
590
+	query_vals[n_query_cols].val.str_val= event->name;
453 591
 	n_query_cols++;
454 592
 
455 593
 	result_cols[body_col=n_result_cols++] = "body" ;
... ...
@@ -476,22 +614,22 @@ str* get_p_notify_body(str user, str host, ev_t* event, str* etag)
476 614
 	if(result== NULL)
477 615
 		return NULL;
478 616
 
479
-	if (result && result->n<=0 )
617
+	if (result->n<=0 )
480 618
 	{
481 619
 		DBG("PRESENCE: get_p_notify_body: The query returned no"
482 620
 				" result\n[username]= %.*s\t[domain]= %.*s\t[event]= %.*s\n",
483
-				user.len, user.s, host.len, host.s, event->stored_name.len, event->stored_name.s);
621
+				uri.user.len, uri.user.s, uri.host.len, uri.host.s,
622
+				event->name.len, event->name.s);
484 623
 		
485 624
 		pa_dbf.free_result(pa_db, result);
486 625
 		result= NULL;
487 626
 
488 627
 		if(event->agg_nbody)
489 628
 		{
490
-			notify_body = event->agg_nbody(&user, &host, NULL, 0, -1);
629
+			notify_body = event->agg_nbody(&uri.user, &uri.host, NULL, 0, -1);
491 630
 			if(notify_body)
492 631
 				goto done;
493
-		}	
494
-			
632
+		}			
495 633
 		return NULL;
496 634
 	}
497 635
 	else
... ...
@@ -620,7 +758,7 @@ str* get_p_notify_body(str user, str host, ev_t* event, str* etag)
620 758
 		pa_dbf.free_result(pa_db, result);
621 759
 		result= NULL;
622 760
 
623
-		notify_body = event->agg_nbody(&user, &host, body_array, n, build_off_n);
761
+		notify_body = event->agg_nbody(&uri.user, &uri.host, body_array, n, build_off_n);
624 762
 	}
625 763
 
626 764
 done:	
... ...
@@ -660,6 +798,11 @@ int free_tm_dlg(dlg_t *td)
660 798
 {
661 799
 	if(td)
662 800
 	{
801
+		if(td->loc_uri.s)
802
+			pkg_free(td->loc_uri.s);
803
+		if(td->rem_uri.s)
804
+			pkg_free(td->rem_uri.s);
805
+
663 806
 		if(td->route_set)
664 807
 			free_rr(&td->route_set);
665 808
 		pkg_free(td);
... ...
@@ -667,10 +810,9 @@ int free_tm_dlg(dlg_t *td)
667 810
 	return 0;
668 811
 }
669 812
 
670
-dlg_t* build_dlg_t (str p_uri, subs_t* subs)
813
+dlg_t* build_dlg_t(subs_t* subs)
671 814
 {
672 815
 	dlg_t* td =NULL;
673
-	str w_uri;
674 816
 	int found_contact = 1;
675 817
 
676 818
 	td = (dlg_t*)pkg_malloc(sizeof(dlg_t));
... ...
@@ -687,7 +829,13 @@ dlg_t* build_dlg_t (str p_uri, subs_t* subs)
687 829
 	td->id.call_id = subs->callid;
688 830
 	td->id.rem_tag = subs->from_tag;
689 831
 	td->id.loc_tag =subs->to_tag;
690
-	td->loc_uri = p_uri;
832
+	
833
+	uandd_to_uri(subs->to_user, subs->to_domain, &td->loc_uri);
834
+	if(td->loc_uri.s== NULL)
835
+	{
836
+		LOG(L_ERR, "PRESENCE:build_dlg_t :ERROR while creating uri\n");
837
+		goto error;
838
+	}
691 839
 
692 840
 	if(subs->contact.len ==0 || subs->contact.s == NULL )
693 841
 	{
... ...
@@ -696,21 +844,19 @@ dlg_t* build_dlg_t (str p_uri, subs_t* subs)
696 844
 	else
697 845
 	{
698 846
 		DBG("CONTACT = %.*s\n", subs->contact.len , subs->contact.s);
699
-
700 847
 		td->rem_target = subs->contact;
701 848
 	}
702 849
 
703
-	uandd_to_uri(subs->from_user, subs->from_domain, &w_uri);
704
-	if(w_uri.s ==NULL)
850
+	uandd_to_uri(subs->from_user, subs->from_domain, &td->rem_uri);
851
+	if(td->rem_uri.s ==NULL)
705 852
 	{
706 853
 		LOG(L_ERR, "PRESENCE:build_dlg_t :ERROR while creating uri\n");
707 854
 		goto error;
708 855
 	}
709 856
 	
710
-	td->rem_uri = w_uri;
711 857
 	if(found_contact == 0)
712 858
 	{
713
-		td->rem_target = w_uri;
859
+		td->rem_target = td->rem_uri;
714 860
 	}
715 861
 	if(subs->record_route.s && subs->record_route.len)
716 862
 	{
... ...
@@ -739,24 +885,15 @@ dlg_t* build_dlg_t (str p_uri, subs_t* subs)
739 885
 	return td;
740 886
 
741 887
 error:
742
-	if(w_uri.s)
743
-	{
744
-		pkg_free(w_uri.s);
745
-		w_uri.s= NULL;
746
-	}
747
-	if(td!=NULL)
748
-		free_tm_dlg(td);
888
+		
889
+	free_tm_dlg(td);
749 890
 
750 891
 	return NULL;
751 892
 }
752 893
 
753
-
754
-int get_subs_dialog(str* p_user, str* p_domain, ev_t* event,str* sender,
755
-		subs_t*** array, int *n)
894
+int get_subs_db(str* pres_uri, pres_ev_t* event, str* sender,
895
+		subs_t** s_array, int* n)
756 896
 {
757