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