6bb363491d65edecb1c95e126643c4b84f427502
[sip-router] / modules_k / presence / notify.c
1 /*
2  * $Id$
3  *
4  * presence module- presence server implementation
5  *
6  * Copyright (C) 2006 Voice Sistem S.R.L.
7  *
8  * This file is part of openser, a free SIP server.
9  *
10  * openser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * openser is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License 
21  * along with this program; if not, write to the Free Software 
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  * History:
25  * --------
26  *  2006-08-15  initial version (anca)
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <libxml/parser.h>
33
34 #include "../../trim.h"
35 #include "../../ut.h"
36 #include "../../globals.h"
37 #include "../../parser/contact/parse_contact.h"
38 #include "../../str.h"
39 #include "../../db/db.h"
40 #include "../../db/db_val.h"
41 #include "../../socket_info.h"
42 #include "../tm/tm_load.h"
43 #include "../pua/hash.h"
44 #include "presentity.h"
45 #include "presence.h"
46 #include "notify.h"
47 #include "utils_func.h"
48
49 #define ALLOC_SIZE 3000
50 #define MAX_FORWARD 70
51
52 extern struct tm_binds tmb;
53 c_back_param* shm_dup_cbparam(subs_t* , subs_t*);
54 void free_cbparam(c_back_param* cb_param);
55
56 void p_tm_callback( struct cell *t, int type, struct tmcb_params *ps);
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
69 void printf_subs(subs_t* subs)
70 {       
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[callid]= %.*s\t[local_cseq]=%d", subs->callid.len, subs->callid.s,
81                         subs->local_cseq); 
82         DBG("\n\t[to_tag]= %.*s\n\t[from_tag]= %.*s",subs->to_tag.len, 
83                 subs->to_tag.s, subs->from_tag.len, subs->from_tag.s);
84         DBG("\n\t[contact]= %.*s\n",subs->contact.len, subs->contact.s);
85 }
86 str* create_winfo_xml(watcher_t* watchers, char* version,str resource, int STATE_FLAG );
87
88 int build_str_hdr(subs_t* subs, int is_body, str** hdr)
89 {
90         str* str_hdr = NULL;    
91         char* subs_expires = NULL;
92         int len = 0;
93         pres_ev_t* event= subs->event;
94         int expires_t;
95         char* status= NULL;
96
97         str_hdr =(str*)pkg_malloc(sizeof(str));
98         if(str_hdr== NULL)
99         {
100                 LOG(L_ERR, "PRESENCE: build_str_hdr:ERROR while allocating memory\n");
101                 return -1;
102         }
103         memset(str_hdr, 0, sizeof(str));
104
105         str_hdr->s = (char*)pkg_malloc(ALLOC_SIZE* sizeof(char));
106         if(str_hdr->s== NULL)
107         {
108                 LOG(L_ERR, "PRESENCE: build_str_hdr:ERROR while allocating memory\n");
109                 pkg_free(str_hdr);
110                 return -1;
111         }       
112
113         strncpy(str_hdr->s ,"Max-Forwards: ", 14);
114         str_hdr->len = 14;
115         len= sprintf(str_hdr->s+str_hdr->len, "%d", MAX_FORWARD);
116         if(len<= 0)
117         {
118                 LOG(L_ERR, "PRESENCE: build_str_hdr:ERROR while printing in string\n");
119                 pkg_free(str_hdr->s);
120                 pkg_free(str_hdr);
121                 return -1;
122         }       
123         str_hdr->len+= len; 
124         strncpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
125         str_hdr->len += CRLF_LEN;
126
127         strncpy(str_hdr->s+str_hdr->len  ,"Event: ", 7);
128         str_hdr->len+= 7;
129         strncpy(str_hdr->s+str_hdr->len, event->name.s, event->name.len);
130         str_hdr->len+= event->name.len;
131         if(subs->event_id.len && subs->event_id.s) 
132         {
133                 strncpy(str_hdr->s+str_hdr->len, ";id=", 4);
134                 str_hdr->len += 4;
135                 strncpy(str_hdr->s+str_hdr->len, subs->event_id.s, subs->event_id.len);
136                 str_hdr->len += subs->event_id.len;
137         }
138         strncpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
139         str_hdr->len += CRLF_LEN;
140
141         strncpy(str_hdr->s+str_hdr->len ,"Contact: <", 10);
142         str_hdr->len += 10;
143         strncpy(str_hdr->s+str_hdr->len, subs->local_contact.s, subs->local_contact.len);
144         str_hdr->len +=  subs->local_contact.len;
145         strncpy(str_hdr->s+str_hdr->len, ">", 1);
146         str_hdr->len += 1;
147         strncpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
148         str_hdr->len += CRLF_LEN;
149         
150         strncpy(str_hdr->s+str_hdr->len,"Subscription-State: ", 20);
151         str_hdr->len+= 20;
152         status= get_status_str(subs->status);
153         if(status== NULL)
154         {
155                 LOG(L_ERR,"PRESENCE: build_str_hdr: ERROR bad status flag= %d\n",
156                                 subs->status);
157                 pkg_free(str_hdr->s);
158                 pkg_free(str_hdr);
159                 return -1;
160         }
161         strcpy(str_hdr->s+str_hdr->len, status);
162         str_hdr->len+= strlen(status);
163         
164         if(subs->expires <= 0)
165         {
166                 expires_t = 0;
167                 subs->status= TERMINATED_STATUS;
168                 subs->reason.s= "timeout";
169                 subs->reason.len= 7;
170         }
171         else
172                 expires_t= subs->expires;
173         
174         if(subs->status== TERMINATED_STATUS)
175         {
176                 DBG( "PRESENCE: build_str_hdr: state = terminated \n");
177                 
178                 strncpy(str_hdr->s+str_hdr->len,";reason=", 8);
179                 str_hdr->len+= 8;
180                 strncpy(str_hdr->s+str_hdr->len, subs->reason.s ,subs->reason.len );
181                 str_hdr->len+= subs->reason.len;
182                 strncpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
183                 str_hdr->len+= CRLF_LEN;
184         }
185         else
186         {       
187                 strncpy(str_hdr->s+str_hdr->len,";expires=", 9);
188                 str_hdr->len+= 9;
189         
190                 subs_expires= int2str(expires_t, &len); 
191
192                 if(subs_expires == NULL || len == 0)
193                 {
194                         LOG(L_ERR, "PRESENCE:built_str_hdr: ERROR while converting int "
195                                         " to str\n");
196                         pkg_free(str_hdr->s);
197                         pkg_free(str_hdr);
198                         return -1;
199                 }
200
201                 DBG("PRESENCE:build_str_hdr: expires = %d\n", expires_t);
202                 DBG("PRESENCE:build_str_hdr: subs_expires : %.*s\n", len , subs_expires);
203
204                 strncpy(str_hdr->s+str_hdr->len,subs_expires ,len );
205                 str_hdr->len += len;
206                 strncpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
207                 str_hdr->len += CRLF_LEN;
208
209                 if(is_body)
210                 {       
211                         strncpy(str_hdr->s+str_hdr->len,"Content-Type: ", 14);
212                         str_hdr->len += 14;
213                         strncpy(str_hdr->s+str_hdr->len, event->content_type.s , event->content_type.len);
214                         str_hdr->len += event->content_type.len;
215                         strncpy(str_hdr->s+str_hdr->len, CRLF, CRLF_LEN);
216                         str_hdr->len += CRLF_LEN;
217                 }
218         }
219         if(str_hdr->len> ALLOC_SIZE)
220         {
221                 LOG(L_ERR, "PRESENCE:build_str_hdr:ERROR buffer size overflown\n");
222                 pkg_free(str_hdr->s);
223                 pkg_free(str_hdr);
224                 return -1;
225
226         }
227         str_hdr->s[str_hdr->len] = '\0';
228         *hdr= str_hdr;
229
230         return 0;
231
232 }
233
234 int get_wi_subs_db(subs_t* subs, watcher_t** watchers)
235 {       
236         watcher_t *w;
237         db_key_t query_cols[6];
238         db_op_t  query_ops[6];
239         db_val_t query_vals[6];
240         db_key_t result_cols[6];
241         db_res_t *result = NULL;
242         db_row_t *row = NULL ;  
243         db_val_t *row_vals = NULL;
244         int n_result_cols = 0;
245         int n_query_cols = 0;
246         int i;
247         int status_col, expires_col, from_user_col, from_domain_col;
248         str from_user, from_domain;
249
250         query_cols[n_query_cols] = "pres_uri";
251         query_ops[n_query_cols] = OP_EQ;
252         query_vals[n_query_cols].type = DB_STR;
253         query_vals[n_query_cols].nul = 0;
254         query_vals[n_query_cols].val.str_val= subs->pres_uri;
255         n_query_cols++;
256
257         query_cols[n_query_cols] = "event";
258         query_ops[n_query_cols] = OP_EQ;
259         query_vals[n_query_cols].type = DB_STR;
260         query_vals[n_query_cols].nul = 0;
261         query_vals[n_query_cols].val.str_val = subs->event->wipeer->name;
262         n_query_cols++;
263
264         result_cols[status_col=n_result_cols++] = "status" ;
265         result_cols[expires_col=n_result_cols++] = "expires";
266         result_cols[from_user_col=n_result_cols++] = "from_user";
267         result_cols[from_domain_col=n_result_cols++] = "from_domain";
268         
269         if (pa_dbf.use_table(pa_db, active_watchers_table) < 0) 
270         {
271                 LOG(L_ERR, "PRESENCE:get_wi_subs_db: Error in use_table\n");
272                 goto error;
273         }
274
275         if (pa_dbf.query (pa_db, query_cols, query_ops, query_vals,
276                  result_cols, n_query_cols, n_result_cols, 0,  &result) < 0) 
277         {
278                 LOG(L_ERR, "PRESENCE:get_wi_subs_db: Error while querying"
279                                 " watchers\n");
280                 goto error;
281         }
282
283         if(result== NULL )
284         {
285                 LOG(L_ERR, "PRESENCE: get_wi_subs_db:The query returned no"
286                                 " result\n");
287                 goto error;
288         }
289
290         if(result->n <= 0)
291         {
292                 DBG("PRESENCEget_wi_subs_db:The query in databse returned no result\n");
293                 pa_dbf.free_result(pa_db, result);
294                 return 0;
295         }
296         
297         for(i=0; i<result->n; i++)
298         {
299                 row = &result->rows[i];
300                 row_vals = ROW_VALUES(row);
301                 
302                 from_user.s= (char*)row_vals[from_user_col].val.string_val;
303                 from_user.len= strlen(from_user.s);
304
305                 from_domain.s= (char*)row_vals[from_domain_col].val.string_val;
306                 from_domain.len= strlen(from_domain.s);
307
308                 w= (watcher_t*)pkg_malloc(sizeof(watcher_t));
309                 if(w== NULL)
310                 {
311                         ERR_MEM("PRESENCE","get_wi_subs_db");
312                 }
313                 w->status= row_vals[status_col].val.int_val;
314                 if(uandd_to_uri(from_user, from_domain, &w->uri)<0)
315                 {
316                         pkg_free(w);
317                         LOG(L_ERR, "PRESENCE:get_wi_subs_db:ERROR while creating"
318                                 " uri\n");
319                         goto error;
320                 }
321                 w->id.s = (char*)pkg_malloc(w->uri.len*2 +1);
322                 if(w->id.s== NULL)
323                 {
324                         LOG(L_ERR,"PRESENCE:get_wi_notify_body: ERROR no more pkg mem\n");
325                         pkg_free(w->uri.s);
326                         pkg_free(w);
327                         goto error;
328                 }
329
330                 to64frombits((unsigned char *)w->id.s,
331                         (const unsigned char*)w->uri.s, w->uri.len);
332    
333                 w->id.len = strlen(w->id.s);
334                 w->event= subs->event->wipeer->name;
335                 
336                 w->next= (*watchers)->next;
337                 (*watchers)->next= w;
338         }
339         
340         pa_dbf.free_result(pa_db, result);
341         return 0;
342
343 error:
344         if(result)
345                 pa_dbf.free_result(pa_db, result);
346         return -1;
347 }
348
349 str* get_wi_notify_body(subs_t* subs, subs_t* watcher_subs)
350 {
351         str* notify_body = NULL;
352         char* version_str;
353         watcher_t *watchers = NULL, *w= NULL;
354         int len = 0;
355         unsigned int hash_code;
356         subs_t* s= NULL;
357
358         version_str = int2str(subs->version, &len);
359         if(version_str ==NULL)
360         {
361                 LOG(L_ERR,"PRESENCE:get_wi_notify_body: ERROR while converting int"
362                                 " to str\n ");
363                 goto error;
364         }
365
366         watchers= (watcher_t*)pkg_malloc(sizeof(watcher_t));
367         if(watchers== NULL)
368         {
369                 ERR_MEM("PRESENCE","get_wi_notify_body");
370         }
371         memset(watchers, 0, sizeof(watcher_t));
372
373         if(watcher_subs != NULL) 
374         {               
375                 w= (watcher_t *)pkg_malloc(sizeof(watcher_t));
376                 if(w== NULL)
377                 {
378                         ERR_MEM("PRESENCE","get_wi_notify_body");
379                 }
380                 memset(w, 0, sizeof(watcher_t));
381
382                 w->status= watcher_subs->status;
383                 uandd_to_uri( watcher_subs->from_user,watcher_subs->from_domain,
384                                                 &w->uri);
385                 if(w->uri.s== NULL)
386                 {
387                         pkg_free(w);
388                         goto error;
389                 }
390
391                 w->id.s = (char *)pkg_malloc(w->uri.len *2 +1);
392                 if(w->id.s== NULL)
393                 {
394                         pkg_free(w->uri.s);
395                         pkg_free(w);
396                         ERR_MEM("PRESENCE","get_wi_notify_body");
397                 }
398                 to64frombits((unsigned char *)w->id.s,
399                                 (const unsigned char*)w->uri.s, w->uri.len );
400                         
401                 w->id.len = strlen(w->id.s);
402                 
403                 w->event= watcher_subs->event->name;
404                 
405                 w->next= watchers->next;
406                 watchers->next= w;
407
408                 goto done;
409         }
410
411         if(fallback2db)
412         {
413                 if(get_wi_subs_db(subs, &watchers)< 0)
414                 {
415                         LOG(L_ERR, "PRESENCE:get_wi_notify_body: ERROR getting watchers"
416                                         "from database\n");
417                         goto error;
418                 }
419         }
420
421         hash_code= core_hash(&subs->pres_uri, &subs->event->name, shtable_size);
422         DBG("PRESENCE:get_wi_notify_body:hash_code= %u\n", hash_code);
423         lock_get(&subs_htable[hash_code].lock);
424
425         s= subs_htable[hash_code].entries;
426
427         while(s->next)
428         {
429                 s= s->next;
430
431                 if(s->expires< (int)time(NULL))
432                 {       
433                         DBG("PRESENCE:get_wi_notify_body:expired record\n");
434                         continue;
435                 }
436
437                 if(fallback2db && s->db_flag!= INSERTDB_FLAG)
438                 {
439                         DBG("PRESENCE:get_wi_notify_body:record already taken"
440                                         " from database\n");
441                         continue;
442                 }
443
444                 if(s->event== subs->event->wipeer && 
445                         s->pres_uri.len== subs->pres_uri.len &&
446                         strncmp(s->pres_uri.s, subs->pres_uri.s,subs->pres_uri.len)== 0)
447                 {
448                         w= (watcher_t*)pkg_malloc(sizeof(watcher_t));
449                         if(w== NULL)
450                         {
451                                 lock_release(&subs_htable[hash_code].lock);
452                                 ERR_MEM("PRESENCE","get_wi_notify_body");
453                         }
454                         w->status= s->status;
455                         if(uandd_to_uri(s->from_user, s->from_domain, &w->uri)<0)
456                         {
457                                 lock_release(&subs_htable[hash_code].lock);
458                                 pkg_free(w);
459                                 LOG(L_ERR, "PRESENCE:get_wi_notify_body:ERROR while creating"
460                                         " uri\n");
461                                 goto error;
462                         }
463                         w->id.s = (char*)pkg_malloc(w->uri.len*2 +1);
464                         if(w->id.s== NULL)
465                         {
466                                 LOG(L_ERR,"PRESENCE:get_wi_notify_body: ERROR no more pkg mem\n");
467                                 lock_release(&subs_htable[hash_code].lock);
468                                 pkg_free(w->uri.s);
469                                 pkg_free(w);
470                                 goto error;
471                         }
472
473                         to64frombits((unsigned char *)w->id.s,
474                                 (const unsigned char*)w->uri.s, w->uri.len);
475    
476                         w->id.len = strlen(w->id.s);
477                         w->event= subs->event->wipeer->name;
478                 
479                         w->next= watchers->next;
480                         watchers->next= w;
481                 }
482         }
483         
484 done:
485         notify_body = create_winfo_xml(watchers,version_str,subs->pres_uri,
486                         FULL_STATE_FLAG );
487         
488         if(watcher_subs == NULL) 
489                 lock_release(&subs_htable[hash_code].lock);
490
491         if(notify_body== NULL)
492         {
493                 LOG(L_ERR, "PRESENCE: get_wi_notify_body: Error in function"
494                                 " create_winfo_xml\n");
495                 goto error;
496         }
497         while(watchers)
498         {       
499                 w= watchers;
500                 if(w->uri.s !=NULL)
501                         pkg_free(w->uri.s);
502                 if(w->id.s !=NULL)
503                         pkg_free(w->id.s);
504                 watchers= watchers->next;
505                 pkg_free(w);
506         }
507         return notify_body;
508
509 error:
510         if(notify_body)
511         {
512                 if(notify_body->s)
513                         xmlFree(notify_body->s);
514                 pkg_free(notify_body);
515         }
516         while(watchers)
517         {       
518                 w= watchers;
519                 if(w->uri.s !=NULL)
520                         pkg_free(w->uri.s);
521                 if(w->id.s !=NULL)
522                         pkg_free(w->id.s);
523                 watchers= watchers->next;
524                 pkg_free(w);
525         }
526
527         return NULL;
528 }
529
530 str* get_p_notify_body(str pres_uri, pres_ev_t* event, str* etag)
531 {
532         db_key_t query_cols[6];
533         db_val_t query_vals[6];
534         db_key_t result_cols[6];
535         db_res_t *result = NULL;
536         int body_col, expires_col, etag_col= 0;
537         str** body_array= NULL;
538         str* notify_body= NULL; 
539         db_row_t *row= NULL ;   
540         db_val_t *row_vals;
541         int n_result_cols = 0;
542         int n_query_cols = 0;
543         int i, n= 0, len;
544         int build_off_n= -1; 
545         str etags;
546         str* body;
547         int size= 0;
548         struct sip_uri uri;
549         unsigned int hash_code;
550
551         if(parse_uri(pres_uri.s, pres_uri.len, &uri)< 0)
552         {
553                 LOG(L_ERR, "PRESENCE: get_p_notify_body: ERROR while parsing uri\n");
554                 return NULL;
555         }
556
557         /* search in hash table if any record exists */
558         hash_code= core_hash(&pres_uri, NULL, phtable_size);
559         if(search_phtable(&pres_uri, event->evp->parsed, hash_code)== NULL)
560         {
561                 DBG("PRESENCE: get_p_notify_body: No record exists in hash_table\n");
562                 if(fallback2db)
563                         goto db_query;
564
565                 /* for pidf manipulation */
566                 if(event->agg_nbody)
567                 {
568                         notify_body = event->agg_nbody(&uri.user, &uri.host, NULL, 0, -1);
569                         if(notify_body)
570                                 goto done;
571                 }                       
572                 return NULL;
573         }
574
575 db_query:
576
577         query_cols[n_query_cols] = "domain";
578         query_vals[n_query_cols].type = DB_STR;
579         query_vals[n_query_cols].nul = 0;
580         query_vals[n_query_cols].val.str_val = uri.host;
581         n_query_cols++;
582
583         query_cols[n_query_cols] = "username";
584         query_vals[n_query_cols].type = DB_STR;
585         query_vals[n_query_cols].nul = 0;
586         query_vals[n_query_cols].val.str_val = uri.user;
587         n_query_cols++;
588
589         query_cols[n_query_cols] = "event";
590         query_vals[n_query_cols].type = DB_STR;
591         query_vals[n_query_cols].nul = 0;
592         query_vals[n_query_cols].val.str_val= event->name;
593         n_query_cols++;
594
595         result_cols[body_col=n_result_cols++] = "body" ;
596         result_cols[expires_col=n_result_cols++] = "expires";
597         result_cols[etag_col=n_result_cols++] = "etag";
598
599         if (pa_dbf.use_table(pa_db, presentity_table) < 0) 
600         {
601                 LOG(L_ERR, "PRESENCE:get_p_notify_body: Error in use_table\n");
602                 return NULL;
603         }
604
605         DBG("PRESENCE:get_p_notify_body: querying presentity\n");
606         if (pa_dbf.query (pa_db, query_cols, 0, query_vals,
607                  result_cols, n_query_cols, n_result_cols, "received_time",  &result) < 0) 
608         {
609                 LOG(L_ERR, "PRESENCE:get_p_notify_body: Error while querying"
610                                 " presentity\n");
611                 if(result)
612                         pa_dbf.free_result(pa_db, result);
613                 return NULL;
614         }
615         
616         if(result== NULL)
617                 return NULL;
618
619
620         if (result->n<=0 )
621         {
622                 DBG("PRESENCE: get_p_notify_body: The query returned no"
623                         " result\n[username]= %.*s\t[domain]= %.*s\t[event]= %.*s\n",
624                         uri.user.len,uri.user.s,uri.host.len,uri.host.s,
625                         event->name.len,event->name.s);
626                 
627                 pa_dbf.free_result(pa_db, result);
628                 result= NULL;
629
630                 if(event->agg_nbody)
631                 {
632                         notify_body = event->agg_nbody(&uri.user, &uri.host, NULL, 0, -1);
633                         if(notify_body)
634                                 goto done;
635                 }                       
636                 return NULL;
637         }
638         else
639         {
640                 n= result->n;
641                 if(event->agg_nbody== NULL )
642                 {
643                         DBG("PRESENCE:get_p_notify_body: Event does not require aggregation\n");
644                         row = &result->rows[n-1];
645                         row_vals = ROW_VALUES(row);
646                         if(row_vals[body_col].val.string_val== NULL)
647                         {
648                                 LOG(L_ERR, "PRESENCE:get_p_notify_body:ERROR NULL notify body record\n");
649                                 goto error;
650                         }
651                         len= strlen(row_vals[body_col].val.string_val);
652                         if(len== 0)
653                         {
654                                 LOG(L_ERR, "PRESENCE:get_p_notify_body:ERROR Empty notify body record\n");
655                                 goto error;
656                         }
657                         notify_body= (str*)pkg_malloc(sizeof(str));
658                         if(notify_body== NULL)
659                         {
660                                 LOG(L_ERR, "PRESENCE:get_p_notify_body: ERROR while allocating memory\n");
661                                 goto error;
662                         }
663                         memset(notify_body, 0, sizeof(str));
664                         notify_body->s= (char*)pkg_malloc( len* sizeof(char));
665                         if(notify_body->s== NULL)
666                         {
667                                 LOG(L_ERR, "PRESENCE:get_p_notify_body: ERROR while allocating memory\n");
668                                 pkg_free(notify_body);
669                                 goto error;
670                         }
671                         memcpy(notify_body->s, row_vals[body_col].val.string_val, len);
672                         notify_body->len= len;
673                         pa_dbf.free_result(pa_db, result);
674                         
675                         return notify_body;
676                 }
677                 
678                 DBG("PRESENCE:get_p_notify_body: Event requires aggregation\n");
679                 
680                 body_array =(str**)pkg_malloc( (n+2) *sizeof(str*));
681                 if(body_array == NULL)
682                 {
683                         ERR_MEM("PRESENCE", "get_p_notify_body");
684                 }
685                 memset(body_array, 0, (n+2) *sizeof(str*));
686
687                 if(etag!= NULL)
688                 {
689                         DBG("PRESENCE:get_p_notify_body:searched etag = %.*s len= %d\n", 
690                                         etag->len, etag->s, etag->len);
691                         DBG( "PRESENCE:get_p_notify_body: etag not NULL\n");
692                         for(i= 0; i< n; i++)
693                         {
694                                 row = &result->rows[i];
695                                 row_vals = ROW_VALUES(row);
696                                 etags.s = (char*)row_vals[etag_col].val.string_val;
697                                 etags.len = strlen(etags.s);
698
699                                 DBG("PRESENCE:get_p_notify_body:etag = %.*s len= %d\n", 
700                                                 etags.len, etags.s, etags.len);
701                                 if( (etags.len == etag->len) && (strncmp(etags.s, etag->s,
702                                                                 etags.len)==0 ) )
703                                 {
704                                         DBG("PRESENCE:get_p_notify_body found etag  \n");
705                                         build_off_n= i;
706                                 }
707                                 len= strlen((char*)row_vals[body_col].val.string_val);
708                                 if(len== 0)
709                                 {
710                                         LOG(L_ERR, "PRESENCE:get_p_notify_body:ERROR Empty notify body record\n");
711                                         goto error;
712                                 }
713                         
714                                 size= sizeof(str)+ len* sizeof(char);
715                                 body= (str*)pkg_malloc(size);
716                                 if(body== NULL)
717                                 {
718                                         ERR_MEM("PRESENCE", "get_p_notify_body");
719                                 }
720                                 memset(body, 0, size);
721                                 size= sizeof(str);
722                                 body->s= (char*)body+ size;
723                                 memcpy(body->s, (char*)row_vals[body_col].val.string_val, len);
724                                 body->len= len;
725
726                                 body_array[i]= body;
727                         }
728                 }       
729                 else
730                 {       
731                         for(i=0; i< n; i++)
732                         {
733                                 row = &result->rows[i];
734                                 row_vals = ROW_VALUES(row);
735                                 
736                                 len= strlen((char*)row_vals[body_col].val.string_val);
737                                 if(len== 0)
738                                 {
739                                         LOG(L_ERR, "PRESENCE:get_p_notify_body:ERROR Empty notify body record\n");
740                                         goto error;
741                                 }
742                                 
743                                 size= sizeof(str)+ len* sizeof(char);
744                                 body= (str*)pkg_malloc(size);
745                                 if(body== NULL)
746                                 {
747                                         LOG(L_ERR, "PRESENCE:get_p_notify_body: ERROR while allocating memory\n");
748                                         goto error;
749                                 }
750                                 memset(body, 0, size);
751                                 size= sizeof(str);
752                                 body->s= (char*)body+ size;
753                                 memcpy(body->s, row_vals[body_col].val.string_val, len);
754                                 body->len= len;
755
756                                 body_array[i]= body;
757                         }                       
758                 }
759                 pa_dbf.free_result(pa_db, result);
760                 result= NULL;
761                 
762                 DBG("PRESENCE: get_p_notify_body: [user]= %.*s\t[domain]= %.*s\n",
763                                 uri.user.len, uri.user.s, uri.host.len, uri.host.s);
764
765                 notify_body = event->agg_nbody(&uri.user, &uri.host, body_array, n, build_off_n);
766         }
767
768 done:   
769         if(body_array!=NULL)
770         {
771                 for(i= 0; i< n; i++)
772                 {
773                         if(body_array[i])
774                                 pkg_free(body_array[i]);
775                 }
776                 pkg_free(body_array);
777         }
778         return notify_body;
779
780 error:
781         if(result!=NULL)
782                 pa_dbf.free_result(pa_db, result);
783
784         if(body_array!=NULL)
785         {
786                 for(i= 0; i< n; i++)
787                 {
788                         if(body_array[i])
789                                 pkg_free(body_array[i]);
790                         else
791                                 break;
792
793                 }
794         
795                 pkg_free(body_array);
796         }
797         return NULL;
798 }
799
800 int free_tm_dlg(dlg_t *td)
801 {
802         if(td)
803         {
804                 if(td->loc_uri.s)
805                         pkg_free(td->loc_uri.s);
806                 if(td->rem_uri.s)
807                         pkg_free(td->rem_uri.s);
808
809                 if(td->route_set)
810                         free_rr(&td->route_set);
811                 pkg_free(td);
812         }
813         return 0;
814 }
815
816 dlg_t* build_dlg_t(subs_t* subs)
817 {
818         dlg_t* td =NULL;
819         int found_contact = 1;
820
821         td = (dlg_t*)pkg_malloc(sizeof(dlg_t));
822         if(td == NULL)
823         {
824                 LOG(L_ERR, "PRESENCE:build_dlg_t: No memory left\n");
825                 return NULL;
826         }
827         memset(td, 0, sizeof(dlg_t));
828
829         td->loc_seq.value = subs->local_cseq;
830         td->loc_seq.is_set = 1;
831
832         td->id.call_id = subs->callid;
833         td->id.rem_tag = subs->from_tag;
834         td->id.loc_tag =subs->to_tag;
835         
836         uandd_to_uri(subs->to_user, subs->to_domain, &td->loc_uri);
837         if(td->loc_uri.s== NULL)
838         {
839                 LOG(L_ERR, "PRESENCE:build_dlg_t :ERROR while creating uri\n");
840                 goto error;
841         }
842
843         if(subs->contact.len ==0 || subs->contact.s == NULL )
844         {
845                 found_contact = 0;
846         }
847         else
848         {
849                 DBG("CONTACT = %.*s\n", subs->contact.len , subs->contact.s);
850                 td->rem_target = subs->contact;
851         }
852
853         uandd_to_uri(subs->from_user, subs->from_domain, &td->rem_uri);
854         if(td->rem_uri.s ==NULL)
855         {
856                 LOG(L_ERR, "PRESENCE:build_dlg_t :ERROR while creating uri\n");
857                 goto error;
858         }
859         
860         if(found_contact == 0)
861         {
862                 td->rem_target = td->rem_uri;
863         }
864         if(subs->record_route.s && subs->record_route.len)
865         {
866                 if(parse_rr_body(subs->record_route.s, subs->record_route.len,
867                         &td->route_set)< 0)
868                 {
869                         LOG(L_ERR, "PRESENCE:build_dlg_t :ERROR in function parse_rr_body\n");
870                         goto error;
871                 }
872         }       
873         td->state= DLG_CONFIRMED ;
874
875         if (subs->sockinfo_str.len) {
876                 int port, proto;
877         str host;
878                 if (parse_phostport (
879                                 subs->sockinfo_str.s,subs->sockinfo_str.len,&host.s,
880                                 &host.len,&port, &proto )) {
881                         LOG (L_ERR,"PRESENCE:build_dlg_t:bad sockinfo string\n");
882                         goto error;
883                 }
884                 td->send_sock = grep_sock_info (
885                         &host, (unsigned short) port, (unsigned short) proto);
886         }
887         
888         return td;
889
890 error:
891                 
892         free_tm_dlg(td);
893
894         return NULL;
895 }
896
897 int get_subs_db(str* pres_uri, pres_ev_t* event, str* sender,
898                 subs_t** s_array, int* n)
899 {
900         db_key_t query_cols[7];
901         db_op_t  query_ops[7];
902         db_val_t query_vals[7];
903         db_key_t result_cols[19];
904         int n_result_cols = 0, n_query_cols = 0;
905         db_row_t *row ; 
906         db_val_t *row_vals ;
907         db_res_t *result = NULL;
908         int from_user_col, from_domain_col, from_tag_col;
909         int to_user_col, to_domain_col, to_tag_col;
910         int expires_col= 0,callid_col, cseq_col, i, status_col, reason_col;
911         int version_col= 0, record_route_col = 0, contact_col = 0;
912         int sockinfo_col= 0, local_contact_col= 0, event_id_col = 0;
913         subs_t s, *s_new;
914         int inc= 0;
915
916         if (pa_dbf.use_table(pa_db, active_watchers_table) < 0) 
917         {
918                 LOG(L_ERR, "PRESENCE:get_subs_db: Error in use_table\n");
919                 return -1;
920         }
921
922         DBG("PRESENCE:get_subs_db:querying database table = active_watchers\n");
923         query_cols[n_query_cols] = "pres_uri";
924         query_ops[n_query_cols] = OP_EQ;
925         query_vals[n_query_cols].type = DB_STR;
926         query_vals[n_query_cols].nul = 0;
927         query_vals[n_query_cols].val.str_val = *pres_uri;
928         n_query_cols++;
929         
930         query_cols[n_query_cols] = "event";
931         query_ops[n_query_cols] = OP_EQ;
932         query_vals[n_query_cols].type = DB_STR;
933         query_vals[n_query_cols].nul = 0;
934         query_vals[n_query_cols].val.str_val = event->name;
935         n_query_cols++;
936
937         query_cols[n_query_cols] = "status";
938         query_ops[n_query_cols] = OP_EQ;
939         query_vals[n_query_cols].type = DB_INT;
940         query_vals[n_query_cols].nul = 0;
941         query_vals[n_query_cols].val.int_val = ACTIVE_STATUS;
942         n_query_cols++;
943
944         if(sender)
945         {       
946                 DBG("PRESENCE:get_subs_db: Should not send Notify to: [uri]= %.*s\n",
947                                  sender->len, sender->s);
948                 query_cols[n_query_cols] = "contact";
949                 query_ops[n_query_cols] = OP_NEQ;
950                 query_vals[n_query_cols].type = DB_STR;
951                 query_vals[n_query_cols].nul = 0;
952                 query_vals[n_query_cols].val.str_val = *sender;
953                 n_query_cols++;
954         }
955
956         result_cols[to_user_col=n_result_cols++]      =   "to_user" ;
957         result_cols[to_domain_col=n_result_cols++]    =   "to_domain";
958         result_cols[from_user_col=n_result_cols++]    =   "from_user" ;
959         result_cols[from_domain_col=n_result_cols++]  =   "from_domain" ;
960         result_cols[event_id_col=n_result_cols++]     =   "event_id";
961         result_cols[from_tag_col=n_result_cols++]     =   "from_tag";
962         result_cols[to_tag_col=n_result_cols++]       =   "to_tag";     
963         result_cols[callid_col=n_result_cols++]       =   "callid";
964         result_cols[cseq_col=n_result_cols++]         =   "local_cseq";
965         result_cols[record_route_col=n_result_cols++] =   "record_route";
966         result_cols[contact_col=n_result_cols++]      =   "contact";
967         result_cols[expires_col=n_result_cols++]      =   "expires";
968         result_cols[status_col=n_result_cols++]       =   "status"; 
969         result_cols[reason_col=n_result_cols++]       =   "reason"; 
970         result_cols[sockinfo_col=n_result_cols++]     =   "socket_info"; 
971         result_cols[local_contact_col=n_result_cols++]=   "local_contact"; 
972         result_cols[version_col=n_result_cols++]      =   "version";
973
974         if (pa_dbf.query(pa_db, query_cols, query_ops, query_vals,result_cols,
975                                 n_query_cols, n_result_cols, 0, &result) < 0) 
976         {
977                 LOG(L_ERR, "PRESENCE:get_subs_db:Error while querying database\n");
978                 if(result)
979                 {
980                         pa_dbf.free_result(pa_db, result);
981                 }
982                 return -1;
983         }
984
985         if(result== NULL)
986                 return -1;
987
988         if(result->n <=0 )
989         {
990                 DBG("PRESENCE: get_subs_db:The query for subscribtion for"
991                         " [uri]= %.*s for [event]= %.*s returned no result\n",
992                         pres_uri->len, pres_uri->s, event->name.len, event->name.s);
993                 pa_dbf.free_result(pa_db, result);
994                 return 0;
995         }
996         DBG("PRESENCE: get_subs_db:found %d dialogs\n", result->n);
997         
998         for(i=0; i<result->n; i++)
999         {
1000                 row = &result->rows[i];
1001                 row_vals = ROW_VALUES(row);     
1002                 
1003         //      if(row_vals[expires_col].val.int_val< (int)time(NULL))
1004         //              continue;
1005
1006                 memset(&s, 0, sizeof(subs_t));
1007
1008                 s.pres_uri= *pres_uri;
1009                 s.to_user.s= (char*)row_vals[to_user_col].val.string_val;
1010                 s.to_user.len=  strlen(s.to_user.s);
1011                 
1012                 s.to_domain.s= (char*)row_vals[to_domain_col].val.string_val;
1013                 s.to_domain.len= strlen(s.to_domain.s);
1014                 
1015                 s.from_user.s= (char*)row_vals[from_user_col].val.string_val;
1016                 s.from_user.len= strlen(s.from_user.s);
1017                 
1018                 s.from_domain.s= (char*)row_vals[from_domain_col].val.string_val;
1019                 s.from_domain.len= strlen(s.from_domain.s);
1020                 
1021                 s.event_id.s=(char*)row_vals[event_id_col].val.string_val;
1022                 s.event_id.len= (s.event_id.s)?strlen(s.event_id.s):0;
1023                 
1024                 s.to_tag.s= (char*)row_vals[to_tag_col].val.string_val;
1025                 s.to_tag.len= strlen(s.to_tag.s);
1026                 
1027                 s.from_tag.s= (char*)row_vals[from_tag_col].val.string_val; 
1028                 s.from_tag.len= strlen(s.from_tag.s);
1029                 
1030                 s.callid.s= (char*)row_vals[callid_col].val.string_val;
1031                 s.callid.len= strlen(s.callid.s);
1032                 
1033                 s.record_route.s=  (char*)row_vals[record_route_col].val.string_val;
1034                 s.record_route.len= (s.record_route.s)?strlen(s.record_route.s):0;
1035
1036                 s.contact.s= (char*)row_vals[contact_col].val.string_val;
1037                 s.contact.len= strlen(s.contact.s);
1038                 
1039                 s.status= row_vals[status_col].val.int_val;
1040                 s.reason.s= (char*)row_vals[reason_col].val.string_val;
1041                 if(s.reason.s)
1042                         s.reason.len= strlen(s.reason.s);
1043
1044                 s.sockinfo_str.s = (char*)row_vals[sockinfo_col].val.string_val;
1045                 s.sockinfo_str.len = s.sockinfo_str.s?strlen(s.sockinfo_str.s):0;
1046
1047                 s.local_contact.s = (char*)row_vals[local_contact_col].val.string_val;
1048                 s.local_contact.len = s.local_contact.s?strlen(s.local_contact.s):0;
1049                 
1050                 s.event= event;
1051                 s.local_cseq = row_vals[cseq_col].val.int_val;
1052                 s.expires = row_vals[expires_col].val.int_val -(int)time(NULL);
1053                 s.version = row_vals[version_col].val.int_val;
1054
1055                 s_new= mem_copy_subs(&s, PKG_MEM_TYPE);
1056                 if(s_new== NULL)
1057                 {
1058                         LOG(L_ERR, "PRESENCE: get_subs_db: ERROR while copying subs_t"
1059                                         " structure\n");
1060                         goto error;
1061                 }
1062                 s_new->next= (*s_array);
1063                 (*s_array)= s_new;
1064                 printf_subs(s_new);     
1065                 inc++;
1066                 
1067         }
1068         DBG("PRESENCE: get_subs_db: left function\n");
1069         pa_dbf.free_result(pa_db, result);
1070         *n= inc;
1071
1072         return 0;
1073
1074 error:
1075         if(result)
1076                 pa_dbf.free_result(pa_db, result);
1077         
1078         return -1;
1079 }
1080
1081 int update_in_list(subs_t* s, subs_t* s_array, int new_rec_no, int n)
1082 {
1083         int i= 0;
1084         subs_t* ls;
1085
1086         ls= s_array;
1087         DBG("PRESENCE:update_in_list....n= %d\n", n);
1088         while(i< new_rec_no)
1089         {
1090                 i++;
1091                 ls= ls->next;
1092         }
1093
1094         for(i = 0; i< n; i++)
1095         {
1096                 DBG("\t%d subs from list\n", i);
1097                 if(ls== NULL)
1098                 {
1099                         LOG(L_ERR, "PRESENCE:update_in_list: ERROR wrong records count\n");
1100                         return -1;
1101                 }
1102                 printf_subs(ls);
1103                 
1104                 if(ls->callid.len== s->callid.len &&
1105                 strncmp(ls->callid.s, s->callid.s, s->callid.len)== 0 &&
1106                 ls->to_tag.len== s->to_tag.len &&
1107                 strncmp(ls->to_tag.s, s->to_tag.s, s->to_tag.len)== 0 &&
1108                 ls->from_tag.len== s->from_tag.len &&
1109                 strncmp(ls->from_tag.s, s->from_tag.s, s->from_tag.len)== 0 )
1110                 {
1111                         ls->local_cseq= s->local_cseq;
1112                         ls->expires= s->expires- (int)time(NULL);
1113                         ls->version= s->version;
1114                         ls->status= s->status;
1115                         return 1;
1116                 }
1117                 ls= ls->next;
1118         }
1119         return -1;
1120 }
1121
1122 subs_t* get_subs_dialog(str* pres_uri, pres_ev_t* event, str* sender)
1123 {
1124         unsigned int hash_code;
1125         subs_t* s= NULL, *s_new;
1126         subs_t* s_array= NULL;
1127         int n= 0, i= 0;
1128         
1129         /* if fallback2db -> should take all dialogs from db
1130          * and the only those dialogs from cache with db_flag= INSERTDB_FLAG */
1131
1132         if(fallback2db)
1133         {
1134                 if(get_subs_db(pres_uri, event, sender, &s_array, &n)< 0)                       
1135                 {
1136                         LOG(L_ERR, "PRESENCE:get_subs_dialog: ERROR getting dialogs from database\n");
1137                         goto error;
1138                 }
1139         }
1140         hash_code= core_hash(pres_uri, &event->name, shtable_size);
1141         
1142         lock_get(&subs_htable[hash_code].lock);
1143
1144         s= subs_htable[hash_code].entries;
1145
1146         while(s->next)
1147         {
1148                 s= s->next;
1149         
1150                 printf_subs(s);
1151                 
1152                 if(s->expires< (int)time(NULL))
1153                 {
1154                         DBG("PRESENCE:get_subs_dialog: This one is expired\n");
1155                         continue;
1156                 }
1157                 
1158                 if((!(s->status== ACTIVE_STATUS && 
1159                         s->event== event && s->pres_uri.len== pres_uri->len &&
1160                         strncmp(s->pres_uri.s, pres_uri->s, pres_uri->len)== 0)) || 
1161                         (sender && sender->len== s->contact.len && 
1162                         strncmp(sender->s, s->contact.s, sender->len)== 0))
1163                         continue;
1164
1165                 if(fallback2db)
1166                 {
1167                         if(s->db_flag== NO_UPDATEDB_FLAG)
1168                         {
1169                                 DBG("PRESENCE:get_subs_dialog:s->db_flag==NO_UPDATEDB_FLAG\n");
1170                                 continue;
1171                         }
1172                         
1173                         if(s->db_flag== UPDATEDB_FLAG)
1174                         {
1175                                 DBG("PRESENCE: get_subs_dialog:s->db_flag== UPDATEDB_FLAG\n");
1176                                 if(n>0 && update_in_list(s, s_array, i, n)< 0)
1177                                 {
1178                                         DBG("PRESENCE: get_subs_dialog: dialog not found in list"
1179                                                         " fetched from database\n");
1180                                         /* insert record */
1181                                 }
1182                                 else
1183                                         continue;                       
1184                         }
1185                 }
1186                 
1187                 DBG("PRESENCE:get_subs_dialog:s->db_flag= INSERTDB_FLAG\n");
1188                 s_new= mem_copy_subs(s, PKG_MEM_TYPE);
1189                 if(s_new== NULL)
1190                 {
1191                         LOG(L_ERR, "PRESENCE: get_subs_dialog: ERROR while copying"
1192                                         " subs_t structure\n");
1193                         lock_release(&subs_htable[hash_code].lock);
1194                         goto error;
1195                 }
1196                 s_new->expires-= (int)time(NULL);
1197                 s_new->next= s_array;
1198                 s_array= s_new;
1199                 i++;
1200         }
1201
1202         lock_release(&subs_htable[hash_code].lock);
1203         DBG("PRESENCE: get_subs_dialog: found %d dialogs( %d in database"
1204                 " and %d in hash_table)\n", n+i , n, i);
1205
1206         return s_array;
1207
1208 error:
1209         free_subs_list(s_array, PKG_MEM_TYPE);
1210         return NULL;
1211         
1212 }
1213
1214 int publ_notify(presentity_t* p, str* body, str* offline_etag, str* rules_doc)
1215 {
1216         str* notify_body = NULL;
1217         subs_t* subs_array= NULL, *s= NULL;
1218         str pres_uri;
1219         int ret_code= -1;
1220
1221         if(uandd_to_uri(p->user, p->domain, &pres_uri)< 0)
1222         {
1223                 LOG(L_ERR, "PRESENCE:publ_notify:ERROR while constructing uri"
1224                                 " from user and domain\n");
1225                 return -1;
1226         }
1227         
1228         subs_array= get_subs_dialog(&pres_uri, p->event , p->sender);
1229         if(subs_array == NULL)
1230         {
1231                 DBG("PRESENCE:publ_notify:Could not find subs_dialog\n");
1232                 ret_code= 0;
1233                 goto done;
1234         }
1235
1236         /* if the event does not require aggregation - we have the final body */
1237         if(p->event->agg_nbody)
1238         {       
1239                 notify_body = get_p_notify_body(pres_uri, p->event , offline_etag);
1240                 if(notify_body == NULL)
1241                 {
1242                         DBG( "PRESENCE:publ_notify: Could not get the"
1243                                         " notify_body\n");
1244                         /* goto error; */
1245                 }
1246         }
1247         
1248         s= subs_array;
1249         while(s)
1250         {
1251                 s->auth_rules_doc= rules_doc;
1252                 if(notify(s, NULL, notify_body?notify_body:body, 0)< 0 )
1253                 {
1254                         LOG(L_ERR, "PRESENCE: publ_notify: Could not send notify for"
1255                                         " %.*s\n", p->event->name.len, p->event->name.s);
1256                 }
1257                 s= s->next;
1258         }
1259         ret_code= 0;
1260
1261 done:
1262         free_subs_list(subs_array, PKG_MEM_TYPE);
1263         
1264         if(notify_body!=NULL)
1265         {
1266                 if(notify_body->s)
1267                 {
1268                         if(     p->event->agg_nbody== NULL && p->event->apply_auth_nbody== NULL)
1269                                 pkg_free(notify_body->s);
1270                         else
1271                                 p->event->free_body(notify_body->s);
1272                 }
1273                 pkg_free(notify_body);
1274         }
1275         pkg_free(pres_uri.s);   
1276         return ret_code;
1277 }       
1278
1279 int query_db_notify(str* pres_uri, pres_ev_t* event, subs_t* watcher_subs )
1280 {
1281         subs_t* subs_array = NULL, *s= NULL;
1282         str* notify_body = NULL;
1283         int ret_code= -1;
1284
1285         subs_array= get_subs_dialog(pres_uri, event , NULL);
1286         if(subs_array == NULL)
1287         {
1288                 DBG("PRESENCE:query_db_notify:Could not get subscription dialog\n");
1289                 ret_code= 1;
1290                 goto done;
1291         }
1292         
1293         if(event->type & PUBL_TYPE)
1294         {
1295                 notify_body = get_p_notify_body(*pres_uri, event,NULL);
1296                 if(notify_body == NULL)
1297                 {
1298                         DBG( "PRESENCE:query_db_notify:Could not get the notify_body\n");
1299                         /* goto error; */
1300                 }
1301         }       
1302
1303         s= subs_array;
1304         
1305         while(s)
1306         {
1307                 if(notify(s, watcher_subs, notify_body, 0)< 0 )
1308                 {
1309                         LOG(L_ERR, "PRESENCE:query_db_notify:Could not send notify for"
1310                                         "%.*s\n", event->name.len, event->name.s);
1311                         goto done;
1312                 }
1313                 s= s->next;
1314         }
1315
1316         ret_code= 1;
1317
1318 done:
1319         free_subs_list(subs_array, PKG_MEM_TYPE);
1320         if(notify_body!=NULL)
1321         {
1322                 if(notify_body->s)
1323                 {
1324                         if(event->type & WINFO_TYPE)
1325                                 pkg_free(notify_body->s);
1326                         else
1327                         if(event->agg_nbody== NULL && event->apply_auth_nbody== NULL)
1328                                 pkg_free(notify_body->s);
1329                         else
1330                                 event->free_body(notify_body->s);
1331                 }
1332                 pkg_free(notify_body);
1333         }
1334
1335         return ret_code;
1336 }
1337
1338 int send_notify_request(subs_t* subs, subs_t * watcher_subs,
1339                 str* n_body,int force_null_body)
1340 {
1341         dlg_t* td = NULL;
1342         str met = {"NOTIFY", 6};
1343         str* str_hdr = NULL;
1344         str* notify_body = NULL;
1345         int result= 0;
1346     c_back_param *cb_param= NULL;
1347         str* final_body= NULL;
1348         
1349         DBG("PRESENCE:send_notify_request:dialog informations:\n");
1350         printf_subs(subs);
1351
1352     /* getting the status of the subscription */
1353
1354         if(force_null_body)
1355         {       
1356                 goto jump_over_body;
1357         }
1358
1359         if(n_body!= NULL && subs->status== ACTIVE_STATUS)
1360         {
1361                 if( subs->event->req_auth)
1362                 {
1363                         
1364                         if(subs->auth_rules_doc &&
1365                                 subs->event->apply_auth_nbody(n_body, subs, &notify_body)< 0)
1366                         {
1367                                 LOG(L_ERR, "PRESENCE:send_notify_request: "
1368                                                 "ERROR in function apply_auth_nbody\n");
1369                                 goto error;
1370                         }
1371                         if(notify_body== NULL)
1372                                 notify_body= n_body;
1373                 }
1374                 else
1375                         notify_body= n_body;
1376         }       
1377         else
1378         {       
1379                 if(subs->status== TERMINATED_STATUS || 
1380                                 subs->status== PENDING_STATUS) 
1381                 {
1382                         DBG("PRESENCE:send_notify_request: state terminated or pending-"
1383                                         " notify body NULL\n");
1384                         notify_body = NULL;
1385                 }
1386                 else  
1387                 {               
1388                         if(subs->event->type & WINFO_TYPE)      
1389                         {       
1390                                 notify_body = get_wi_notify_body(subs, watcher_subs);
1391                                 if(notify_body == NULL)
1392                                 {
1393                                         DBG("PRESENCE:send_notify_request: Could not get the "
1394                                                         "notify_body\n");
1395                                         goto error;
1396                                 }
1397                         }
1398                         else
1399                         {
1400                                 notify_body = get_p_notify_body(subs->pres_uri,
1401                                                 subs->event, NULL);
1402                                 if(notify_body == NULL || notify_body->s== NULL)
1403                                 {
1404                                         DBG("PRESENCE:send_notify_request: Could not get "
1405                                                         "the notify_body\n");
1406                                 }
1407                                 else            /* apply authorization rules if exists */
1408                                 if(subs->event->req_auth)
1409                                 {
1410                                          
1411                                         if(subs->auth_rules_doc && 
1412                                         subs->event->apply_auth_nbody(notify_body,subs,&final_body)<0)
1413                                         {
1414                                                 LOG(L_ERR, "PRESENCE:send_notify_request: ERROR in function"
1415                                                                 " apply_auth\n");
1416                                                 goto error;
1417                                         }
1418                                         if(final_body)
1419                                         {
1420                                                 xmlFree(notify_body->s);
1421                                                 pkg_free(notify_body);
1422                                                 notify_body= final_body;
1423                                         }       
1424                                 }       
1425                         }               
1426                 }
1427         }
1428         
1429 jump_over_body:
1430
1431         /* build extra headers */
1432         if( build_str_hdr( subs, notify_body?1:0, &str_hdr)< 0 )
1433         {
1434                 LOG(L_ERR, "PRESENCE:send_notify_request:ERROR while building headers \n");
1435                 goto error;
1436         }       
1437         DBG("PRESENCE:send_notify_request: headers:\n%.*s\n", str_hdr->len, str_hdr->s);
1438
1439         /* construct the dlg_t structure */
1440         td = build_dlg_t(subs);
1441         if(td ==NULL)
1442         {
1443                 LOG(L_ERR, "PRESENCE:send_notify_request:ERROR while building dlg_t structure \n");
1444                 goto error;     
1445         }
1446
1447         if(subs->event->type == WINFO_TYPE && watcher_subs )
1448         {
1449                 DBG("PRESENCE: :send_notify_requestSend notify for presence on callback\n");
1450                 watcher_subs->send_on_cback = 1;                        
1451         }
1452         cb_param = shm_dup_cbparam(watcher_subs, subs);
1453         if(cb_param == NULL)
1454         {
1455                 LOG(L_ERR, "PRESENCE:send_notify_request:ERROR while duplicating cb_param in"
1456                         " share memory\n");
1457                 goto error;     
1458         }       
1459
1460         result = tmb.t_request_within
1461                 (&met,                                                       
1462                 str_hdr,                               
1463                 notify_body,                           
1464                 td,                                                       
1465                 p_tm_callback,                                  
1466                 (void*)cb_param);                               
1467
1468         if(result< 0)
1469         {
1470                 LOG(L_ERR, "PRESENCE:send_notify_request: ERROR in function tmb.t_request_within\n");
1471                 free_cbparam(cb_param);
1472                 goto error;     
1473         }
1474         free_tm_dlg(td);
1475         
1476         pkg_free(str_hdr->s);
1477         pkg_free(str_hdr);
1478         
1479         if((int)n_body!= (int)notify_body)
1480         {
1481                 if(notify_body!=NULL)
1482                 {
1483                         if(notify_body->s!=NULL)
1484                         {
1485                                 if(subs->event->type& WINFO_TYPE)
1486                                         xmlFree(notify_body->s);
1487                                 else
1488                                 if(subs->event->apply_auth_nbody== NULL && subs->event->agg_nbody== NULL)
1489                                         pkg_free(notify_body->s);
1490                                 else
1491                                 subs->event->free_body(notify_body->s);
1492                         }
1493                         pkg_free(notify_body);
1494                 }
1495         }       
1496         return 0;
1497
1498 error:
1499         free_tm_dlg(td);
1500         if(str_hdr!=NULL)
1501         {
1502                 if(str_hdr->s)
1503                         pkg_free(str_hdr->s);
1504                 pkg_free(str_hdr);
1505         }
1506         if((int)n_body!= (int)notify_body)
1507         {
1508                 if(notify_body!=NULL)
1509                 {
1510                         if(notify_body->s!=NULL)
1511                         {
1512                                 if(subs->event->type& WINFO_TYPE)
1513                                         xmlFree(notify_body->s);
1514                                 else
1515                                 if(subs->event->apply_auth_nbody== NULL && subs->event->agg_nbody== NULL)
1516                                         pkg_free(notify_body->s);
1517                                 else
1518                                 subs->event->free_body(notify_body->s);
1519                         }
1520                         pkg_free(notify_body);
1521                 }
1522         }       
1523         return -1;
1524 }
1525
1526
1527 int notify(subs_t* subs, subs_t * watcher_subs,str* n_body,int force_null_body)
1528 {
1529         /* update first in hash table and the send Notify */
1530         if(subs->expires!= 0)
1531         {
1532                 if(update_shtable(subs, LOCAL_TYPE)< 0)
1533                 {
1534                         if(subs->db_flag!= INSERTDB_FLAG && fallback2db)
1535                         {
1536                                 DBG("PRESENCE:notify: record not found in subs htable\n");
1537                                 if(update_subs_db(subs, LOCAL_TYPE)< 0)
1538                                 {
1539                                         LOG(L_ERR, "PRESENCE:notify:ERROR updating subscription"
1540                                                         " in database\n");
1541                                         return -1;
1542                                 }
1543                         }
1544                         else
1545                         {
1546                                 LOG(L_ERR, "PRESENCE:notify:ERROR record not found"
1547                                                 " in subs htable\n");
1548                                 return -1;
1549                         }
1550                 }
1551         }
1552
1553         if(send_notify_request(subs, watcher_subs, n_body, force_null_body)< 0)
1554         {
1555                 LOG(L_ERR,"PRESENCE:notify: ERROR send Notify not successful\n");
1556                 return -1;
1557         }
1558         return 0;       
1559 }
1560
1561 void p_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
1562 {
1563         if(ps->param==NULL || *ps->param==NULL || 
1564                         ((c_back_param*)(*ps->param))->pres_uri.s == NULL || 
1565                         ((c_back_param*)(*ps->param))->ev_name.s== NULL ||
1566                         ((c_back_param*)(*ps->param))->to_tag.s== NULL)
1567         {
1568                 DBG("PRESENCE p_tm_callback: message id not received\n");
1569                 if(*ps->param !=NULL  )
1570                         free_cbparam((c_back_param*)(*ps->param));
1571                 return;
1572         }
1573         
1574         DBG( "PRESENCE:p_tm_callback:completed with status %d [to_tag:%.*s]\n",
1575                         ps->code,((c_back_param*)(*ps->param))->to_tag.len,
1576                         ((c_back_param*)(*ps->param))->to_tag.s);
1577
1578         if(ps->code >= 300)
1579         {
1580                 c_back_param*  cb= (c_back_param*)(*ps->param);
1581                 
1582                 delete_shtable(cb->pres_uri, cb->ev_name, cb->to_tag);
1583
1584                 delete_db_subs(cb->pres_uri, cb->ev_name, cb->to_tag);
1585
1586                 goto done;
1587         }       
1588         /* send a more accurate Notify for presence depending on the reply for winfo*/
1589         if(((c_back_param*)(*ps->param))->wi_subs!= NULL)
1590         {
1591                 /* if an error message is received as a reply for the winfo Notify 
1592           * send a Notify for presence with no body (the stored presence information is 
1593           * not valid ) */
1594
1595                 if(ps->code >= 300)
1596                 {
1597                         if(notify( ((c_back_param*)(*ps->param))->wi_subs, NULL, NULL, 1)< 0)
1598                         {
1599                                 LOG(L_ERR, "PRESENCE:update_subscribtion: Could not send"
1600                                         " notify for presence\n");
1601                         }
1602                 }
1603                 else
1604                 {
1605                         if(notify( ((c_back_param*)(*ps->param))->wi_subs, NULL, NULL, 0)< 0)
1606                         {
1607                                 LOG(L_ERR, "PRESENCE:update_subscribtion: Could not send"
1608                                         " notify for presence\n");
1609                         }
1610                 }       
1611         }
1612         else
1613                 DBG("PRESENCE:p_tm_callback: Empty wi_subs parameter\n");
1614
1615 done:
1616         if(*ps->param !=NULL  )
1617                 free_cbparam((c_back_param*)(*ps->param));
1618         return ;
1619
1620 }
1621
1622 void free_cbparam(c_back_param* cb_param)
1623 {
1624         if(cb_param!= NULL)
1625         {
1626                 if(cb_param->pres_uri.s)
1627                         shm_free(cb_param->pres_uri.s);
1628                 if(cb_param->ev_name.s)
1629                         shm_free(cb_param->ev_name.s);
1630                 if(cb_param->wi_subs)
1631                         shm_free(cb_param->wi_subs);
1632                 if(cb_param->to_tag.s)
1633                         shm_free(cb_param->to_tag.s);
1634                 shm_free(cb_param);
1635         }
1636
1637 }
1638
1639 c_back_param* shm_dup_cbparam(subs_t* w_subs, subs_t* subs)
1640 {
1641         c_back_param* cb_param = NULL;
1642
1643         cb_param= (c_back_param*)shm_malloc(sizeof(c_back_param));
1644         if(cb_param== NULL)
1645         {
1646                 ERR_MEM("PRESENCE","shm_dup_cbparam");
1647         }
1648         memset(cb_param, 0, sizeof(c_back_param));
1649
1650         cb_param->pres_uri.s= (char*)shm_malloc(subs->pres_uri.len* sizeof(char));
1651         if(cb_param->pres_uri.s== NULL)
1652         {
1653                 ERR_MEM("PRESENCE","shm_dup_cbparam");
1654         }
1655         memcpy(cb_param->pres_uri.s, subs->pres_uri.s, subs->pres_uri.len);
1656         cb_param->pres_uri.len= subs->pres_uri.len;
1657
1658         cb_param->ev_name.s= (char*)shm_malloc
1659                         (subs->event->name.len* sizeof(char));
1660         if(cb_param->ev_name.s== NULL)
1661         {
1662                 ERR_MEM("PRESENCE","shm_dup_cbparam");
1663         }
1664         memcpy(cb_param->ev_name.s, subs->event->name.s,
1665                         subs->event->name.len);
1666         cb_param->ev_name.len= subs->event->name.len;
1667
1668         cb_param->to_tag.s= (char*)shm_malloc(subs->to_tag.len*sizeof(char));
1669         if(cb_param->to_tag.s== NULL)
1670         {
1671                 ERR_MEM("PRESENCE","shm_dup_cbparam");
1672         }
1673         memcpy(cb_param->to_tag.s, subs->to_tag.s ,subs->to_tag.len) ;
1674         cb_param->to_tag.len= subs->to_tag.len;
1675
1676         if(w_subs && w_subs->send_on_cback)
1677         {
1678                 cb_param->wi_subs= mem_copy_subs(w_subs, SHM_MEM_TYPE);
1679                 if(cb_param->wi_subs== NULL)
1680                 {
1681                         LOG(L_ERR, "PRESENCE: shm_dup_cbparam: ERROR while copying subs_t"
1682                                         " structure\n");
1683                         goto error;
1684                 }
1685         }
1686         
1687         return cb_param;
1688
1689 error:
1690         free_cbparam(cb_param);
1691         return NULL;
1692 }
1693
1694
1695 str* create_winfo_xml(watcher_t* watchers, char* version,
1696                 str resource, int STATE_FLAG )
1697 {
1698         xmlDocPtr doc = NULL;       
1699     xmlNodePtr root_node = NULL, node = NULL;
1700         xmlNodePtr w_list_node = NULL;  
1701         char content[200];
1702         str *body= NULL;
1703         char* res= NULL;
1704         watcher_t* w;
1705
1706     LIBXML_TEST_VERSION;
1707     
1708         doc = xmlNewDoc(BAD_CAST "1.0");
1709     root_node = xmlNewNode(NULL, BAD_CAST "watcherinfo");
1710     xmlDocSetRootElement(doc, root_node);
1711
1712     xmlNewProp(root_node, BAD_CAST "xmlns",
1713                         BAD_CAST "urn:ietf:params:xml:ns:watcherinfo");
1714     xmlNewProp(root_node, BAD_CAST "version", BAD_CAST version );
1715    
1716         if(STATE_FLAG & FULL_STATE_FLAG)
1717         {
1718                 if( xmlNewProp(root_node, BAD_CAST "state", BAD_CAST "full") == NULL)
1719                 {
1720                         LOG(L_ERR, "PRESENCE: create_winfo_xml: ERROR while adding new"
1721                                         "attribute\n");
1722                         goto error;
1723                 }
1724         }
1725         else    
1726         {       
1727                 if( xmlNewProp(root_node, BAD_CAST "state", 
1728                                         BAD_CAST "partial")== NULL) 
1729                 {
1730                         LOG(L_ERR, "PRESENCE: create_winfo_xml: ERROR while adding new"
1731                                         "attribute\n");
1732                         goto error;
1733                 }
1734         }
1735
1736         w_list_node =xmlNewChild(root_node, NULL, BAD_CAST "watcher-list",NULL);
1737         if( w_list_node == NULL)
1738         {
1739                 LOG(L_ERR, "PRESENCE: create_winfo_xml: ERROR while adding child\n");
1740                 goto error;
1741         }
1742         res= (char*)pkg_malloc(sizeof(char)*(resource.len+ 1));
1743         if(res== NULL)
1744         {
1745                 ERR_MEM("PRESENCE","create_winfo_xml");
1746         }
1747         memcpy(res, resource.s, resource.len);
1748         res[resource.len]= '\0';
1749
1750         xmlNewProp(w_list_node, BAD_CAST "resource", BAD_CAST res);
1751         xmlNewProp(w_list_node, BAD_CAST "package", BAD_CAST "presence");
1752
1753         pkg_free(res);
1754
1755         w= watchers->next;
1756         while(w)
1757         {
1758                 strncpy( content,w->uri.s, w->uri.len);
1759                 content[ w->uri.len ]='\0';
1760                 node = xmlNewChild(w_list_node, NULL, BAD_CAST "watcher",
1761                                 BAD_CAST content) ;
1762                 if( node ==NULL)
1763                 {
1764                         LOG(L_ERR, "PRESENCE: create_winfo_xml: ERROR while adding"
1765                                         " child\n");
1766                         goto error;
1767                 }
1768                 if(xmlNewProp(node, BAD_CAST "id", BAD_CAST w->id.s)== NULL)
1769                 {
1770                         LOG(L_ERR, "PRESENCE: create_winfo_xml: ERROR while adding"
1771                                         " new attribute\n");
1772                         goto error;
1773                 }       
1774                 
1775                 if(xmlNewProp(node, BAD_CAST "event", BAD_CAST "subscribe")== NULL)
1776                 {
1777                         LOG(L_ERR, "PRESENCE: create_winfo_xml: ERROR while adding new"
1778                                         " attribute\n");
1779                         goto error;
1780                 }       
1781                 
1782                 if(xmlNewProp(node, BAD_CAST "status", 
1783                                         BAD_CAST get_status_str(w->status) )== NULL)
1784                 {
1785                         LOG(L_ERR, "PRESENCE: create_winfo_xml: ERROR while adding"
1786                                         " new attribute\n");
1787                         goto error;
1788                 }
1789                 w= w->next;
1790         }
1791     body = (str*)pkg_malloc(sizeof(str));
1792         if(body == NULL)
1793         {
1794                 ERR_MEM("PRESENCE","create_winfo_xml"); 
1795         }
1796         memset(body, 0, sizeof(str));
1797
1798         xmlDocDumpFormatMemory(doc,(xmlChar**)(void*)&body->s, &body->len, 1);
1799
1800         xmlFreeDoc(doc);
1801
1802         xmlCleanupParser();
1803
1804     xmlMemoryDump();
1805
1806     return body;
1807
1808 error:
1809     if(doc)
1810                 xmlFreeDoc(doc);
1811         return NULL;
1812 }
1813
1814
1815
1816
1817         
1818
1819
1820