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