- replaced LOG/DBG with LM_
[sip-router] / modules_k / presence / publish.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 <time.h>
30
31 #include "../../ut.h"
32 #include "../../str.h"
33 #include "../../parser/parse_to.h"
34 #include "../../parser/parse_uri.h" 
35 #include "../../parser/parse_expires.h" 
36 #include "../../parser/parse_event.h" 
37 #include "../../parser/parse_content.h" 
38 #include "../../lock_ops.h"
39 #include "../../hash_func.h"
40 #include "../../db/db.h"
41 #include "presence.h"
42 #include "notify.h"
43 #include "utils_func.h"
44 #include "publish.h"
45 #include "presentity.h"
46
47 extern db_con_t* pa_db;
48 extern db_func_t pa_dbf;
49 extern gen_lock_set_t* set;
50 extern int counter ;
51 extern int pid;
52 extern int startup_time;
53
54 static str pu_400a_rpl = str_init("Bad request");
55 static str pu_400b_rpl = str_init("Invalid request");
56
57 void msg_presentity_clean(unsigned int ticks,void *param)
58 {
59         db_key_t db_keys[2];
60         db_val_t db_vals[2];
61         db_op_t  db_ops[2] ;
62         db_key_t result_cols[6];
63         db_res_t *result = NULL;
64         db_row_t *row ; 
65         db_val_t *row_vals ;
66         int i =0, size= 0;
67         presentity_t** p= NULL;
68         presentity_t* pres= NULL;
69         int n= 0;
70         int event_col, etag_col, user_col, domain_col;
71         event_t e;
72         str user, domain, etag, event;
73         int n_result_cols= 0;
74         str pres_uri;
75         str* rules_doc= NULL;
76
77         if (pa_dbf.use_table(pa_db, presentity_table) < 0) 
78         {
79                 LM_ERR("in use_table\n");
80                 return ;
81         }
82         
83         LM_DBG("cleaning expired presentity information\n");
84
85         db_keys[0] ="expires";
86         db_ops[0] = OP_LT;
87         db_vals[0].type = DB_INT;
88         db_vals[0].nul = 0;
89         db_vals[0].val.int_val = (int)time(NULL);
90                 
91         result_cols[user_col= n_result_cols++] = "username";
92         result_cols[domain_col=n_result_cols++] = "domain";
93         result_cols[etag_col=n_result_cols++] = "etag";
94         result_cols[event_col=n_result_cols++] = "event";
95
96         if(pa_dbf.query(pa_db, db_keys, db_ops, db_vals, result_cols,
97                                                 1, n_result_cols, "username", &result )< 0)
98         {
99                 LM_ERR("querying database for expired messages\n");
100                 if(result)
101                         pa_dbf.free_result(pa_db, result);
102                 return;
103         }
104         if(result== NULL)
105                 return;
106
107         if(result && result->n<= 0)
108         {
109                 pa_dbf.free_result(pa_db, result);      
110                 return;
111         }
112         LM_DBG("found n= %d expires messages\n ",result->n);
113
114         n= result->n;
115         
116         p= (presentity_t**)pkg_malloc(n* sizeof(presentity_t*));
117         if(p== NULL)
118         {
119                 ERR_MEM(PKG_MEM_STR);   
120         }
121         memset(p, 0, n* sizeof(presentity_t*));
122
123         for(i = 0; i< n; i++)
124         {       
125                 row = &result->rows[i];
126                 row_vals = ROW_VALUES(row);     
127         
128                 user.s= (char*)row_vals[user_col].val.string_val;
129                 user.len= strlen(user.s);
130                 
131                 domain.s= (char*)row_vals[domain_col].val.string_val;
132                 domain.len= strlen(domain.s);
133
134                 etag.s= (char*)row_vals[etag_col].val.string_val;
135                 etag.len= strlen(etag.s);
136
137                 event.s= (char*)row_vals[event_col].val.string_val;
138                 event.len= strlen(event.s);
139                 
140                 size= sizeof(presentity_t)+ user.len+ domain.len+ etag.len; 
141                 pres= (presentity_t*)pkg_malloc(size);
142                 if(pres== NULL)
143                 {
144                         ERR_MEM(PKG_MEM_STR);
145                 }
146                 memset(pres, 0, size);
147                 size= sizeof(presentity_t);
148                 
149                 pres->user.s= (char*)pres+ size;        
150                 memcpy(pres->user.s, user.s, user.len);
151                 pres->user.len= user.len;
152                 size+= user.len;
153
154                 pres->domain.s= (char*)pres+ size;
155                 memcpy(pres->domain.s, domain.s, domain.len);
156                 pres->domain.len= domain.len;
157                 size+= domain.len;
158
159                 pres->etag.s= (char*)pres+ size;
160                 memcpy(pres->etag.s, etag.s, etag.len);
161                 pres->etag.len= etag.len;
162                 size+= etag.len;
163                         
164                 pres->event= contains_event(&event, &e);
165                 if(pres->event== NULL)
166                 {
167                         LM_ERR("event not found\n");
168                         goto error;
169                 }       
170                 p[i]= pres;
171
172                 /* delete from hash table */
173                 if(uandd_to_uri(user, domain, &pres_uri)< 0)
174                 {
175                         LM_ERR("constructing uri\n");
176                         goto error;
177                 }
178
179                 if(delete_phtable(&pres_uri, e.parsed)< 0)
180                 {
181                         LM_ERR("deleting from pres hash table\n");
182                         pkg_free(pres_uri.s);
183                         goto error;
184                 }
185                 pkg_free(pres_uri.s);
186
187         }
188         pa_dbf.free_result(pa_db, result);
189         result= NULL;
190         
191         for(i= 0; i<n ; i++)
192         {
193                 LM_DBG("found expired publish for [user]=%.*s  [domanin]=%.*s\n",
194                         p[i]->user.len,p[i]->user.s, p[i]->domain.len, p[i]->domain.s);
195                 
196                 rules_doc= NULL;
197                 
198                 if(p[i]->event->get_rules_doc && 
199                 p[i]->event->get_rules_doc(&p[i]->user, &p[i]->domain, &rules_doc)< 0)
200                 {
201                         LM_ERR("getting rules doc\n");
202                         goto error;
203                 }
204                 if(publ_notify( p[i], NULL, &p[i]->etag, rules_doc)< 0)
205                 {
206                         LM_ERR("sending Notify request\n");
207                         goto error;
208                 }
209                 if(rules_doc)
210                 {
211                         if(rules_doc->s)
212                                 pkg_free(rules_doc->s);
213                         pkg_free(rules_doc);
214                 }
215                 rules_doc= NULL;
216         }
217
218         if (pa_dbf.use_table(pa_db, presentity_table) < 0) 
219         {
220                 LM_ERR("in use_table\n");
221                 goto error;
222         }
223         
224         if (pa_dbf.delete(pa_db, db_keys, db_ops, db_vals, 1) < 0) 
225                 LM_ERR("cleaning expired messages\n");
226         
227         for(i= 0; i< n; i++)
228         {
229                 if(p[i])
230                         pkg_free(p[i]);
231         }
232         pkg_free(p);
233
234         return;
235
236 error:
237         if(result)
238                 pa_dbf.free_result(pa_db, result);
239         if(p)
240         {
241                 for(i= 0; i< n; i++)
242                 {
243                         if(p[i])
244                                 pkg_free(p[i]);
245                         else
246                                 break;
247                 }
248                 pkg_free(p);
249         }
250         if(rules_doc)
251         {
252                 if(rules_doc->s)
253                         pkg_free(rules_doc->s);
254                 pkg_free(rules_doc);
255         }
256
257         return; 
258 }
259
260 /**
261  * PUBLISH request handling
262  *
263  */
264 int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
265 {
266         struct sip_uri puri;
267         str body;
268         int lexpire;
269         presentity_t* presentity = 0;
270         struct hdr_field* hdr;
271         int found= 0, etag_gen = 0;
272         str etag={0, 0};
273         int error_ret = -1; 
274         str* sender= NULL;
275         static char buf[256];
276         int buf_len= 255;
277         pres_ev_t* event= NULL;
278         str pres_user;
279         str pres_domain;
280         struct sip_uri pres_uri;
281
282         counter++;
283         if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
284         {
285                 LM_ERR("parsing headers\n");
286                 if (slb.reply(msg, 400, &pu_400a_rpl) == -1)
287                         LM_ERR("Error while sending 400 reply\n");
288                 else
289                         error_ret = 0;
290                 return error_ret;
291         }
292         memset(&body, 0, sizeof(str));
293         
294         /* inspecting the Event header field */
295         
296         if(msg->event && msg->event->body.len > 0)
297         {
298                 if (!msg->event->parsed && (parse_event(msg->event) < 0))
299                 {
300                         LM_ERR("cannot parse Event header\n");
301                         goto error;
302                 }
303                 if(((event_t*)msg->event->parsed)->parsed & EVENT_OTHER)
304                 {       
305                         goto unsupported_event;
306                 }
307         }
308         else
309                 goto unsupported_event;
310
311         /* search event in the list */
312         event= search_event((event_t*)msg->event->parsed);
313         if(event== NULL)
314         {
315                 goto unsupported_event;
316         }
317         
318         /* examine the SIP-If-Match header field */
319         hdr = msg->headers;
320         while (hdr!= NULL)
321         {
322                 if(strncmp(hdr->name.s, "SIP-If-Match",12)==0|| 
323                                 strncmp(hdr->name.s,"Sip-If-Match",12)==0 )
324                 {
325                         found = 1;
326                         break;
327                 }
328                 hdr = hdr->next;
329         }
330         if(found==0 )
331         {
332                 LM_DBG("SIP-If-Match header not found\n");
333                 etag.s = generate_ETag(0);
334                 if(etag.s == NULL)
335                 {
336                         LM_ERR("when generating etag\n");
337                         return -1;
338                 }
339                 etag.len=(strlen(etag.s));
340                 etag_gen=1;
341                 LM_DBG("new etag  = %.*s \n", etag.len, etag.s);
342         }
343         else
344         {
345                 LM_DBG("SIP-If-Match header found\n");
346                 etag.s = (char*)pkg_malloc((hdr->body.len+ 1)* sizeof(char));
347                 if(etag.s== NULL)
348                 {
349                         ERR_MEM(PKG_MEM_STR);
350                 }
351                 memcpy(etag.s, hdr->body.s, hdr->body.len );
352                 etag.len = hdr->body.len;        
353                 etag.s[ etag.len] = '\0';
354                 LM_DBG("existing etag  = %.*s \n", etag.len, etag.s);
355         }
356
357         /* examine the expire header field */
358         if(msg->expires && msg->expires->body.len > 0)
359         {
360                 if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
361                 {
362                         LM_ERR("cannot parse Expires header\n");
363                         goto error;
364                 }
365                 lexpire = ((exp_body_t*)msg->expires->parsed)->val;
366                 LM_DBG("Expires header found, value= %d\n", lexpire);
367
368         }
369         else 
370         {
371                 LM_DBG("'expires' not found; default=%d\n",     event->default_expires);
372                 lexpire = event->default_expires;
373         }
374         if(lexpire > max_expires)
375                 lexpire = max_expires;
376
377         /* get pres_uri from Request-URI*/
378         if( parse_uri(msg->first_line.u.request.uri.s, 
379                                 msg->first_line.u.request.uri.len, &pres_uri)< 0)
380         {
381                 LM_ERR("parsing Request URI\n");
382                 goto error;
383         }
384         pres_user= pres_uri.user;
385         pres_domain= pres_uri.host;
386
387         if (!msg->content_length) 
388         {
389                 LM_ERR("no Content-Length header found!\n");
390                 goto error;
391         }       
392
393         /* process the body */
394         if ( get_content_length(msg) == 0 )
395         {
396                 body.s = NULL;
397                 if (etag_gen)
398                 {
399                         LM_ERR("No E-Tag and no body found\n");
400                         if (slb.reply(msg, 400, &pu_400b_rpl) == -1)
401                                 LM_ERR("sending 400 Invalid request reply\n");
402                         else
403                                 error_ret = 0;
404                         goto error;
405                 }
406         }
407         else
408         {
409                 body.s=get_body(msg);
410                 if (body.s== NULL) 
411                 {
412                         LM_ERR("cannot extract body\n");
413                         goto error;
414                 }
415                 body.len= get_content_length( msg );
416         }       
417         memset(&puri, 0, sizeof(struct sip_uri));
418         if(sender_uri && sender_uri!= "")
419         {
420                 sender=(str*)pkg_malloc(sizeof(str));
421                 if(sender== NULL)
422                 {
423                         ERR_MEM(PKG_MEM_STR);
424                 }       
425                 if(xl_printf(msg, (xl_elem_t*)sender_uri, buf, &buf_len)<0)
426                 {
427                         LM_ERR("cannot print the format\n");
428                         goto error;
429                 }
430                 if(parse_uri(buf, buf_len, &puri)!=0)
431                 {
432                         LM_ERR("bad owner SIP address!\n");
433                         goto error;
434                 } else 
435                 {
436                         LM_DBG("using user id [%.*s]\n",buf_len,buf);
437                 }
438                 sender->s= buf;
439                 sender->len= buf_len;
440         }
441         /* call event specific handling function*/
442         if(event->evs_publ_handl)
443         {
444                 if(event->evs_publ_handl(msg)< 0)
445                 {
446                         LM_ERR("in event specific publish handling\n");
447                         goto error;
448                 }
449         }
450
451         /* now we have all the necessary values */
452         /* fill in the filds of the structure */
453
454         presentity= new_presentity(&pres_domain, &pres_user, lexpire, event, &etag, sender);
455         if(presentity== NULL)
456         {
457                 LM_ERR("creating presentity structure\n");
458                 goto error;
459         }
460
461         /* querry the database and update or insert */
462         if(update_presentity(msg, presentity, &body, etag_gen) <0)
463         {
464                 LM_ERR("when updating presentity\n");
465                 goto error;
466         }
467
468         if(presentity)
469                 pkg_free(presentity);
470         if(etag.s)
471                 pkg_free(etag.s);
472         if(sender)
473                 pkg_free(sender);
474
475         return 1;
476
477 error:
478         
479         if(presentity)
480                 pkg_free(presentity);
481         if(etag.s)
482                 pkg_free(etag.s);
483         if(sender)
484                 pkg_free(sender);
485         
486         return error_ret;
487
488 unsupported_event:
489         
490         LM_ERR("Missing or unsupported event header field value\n");
491                 
492         if(msg->event && msg->event->body.s && msg->event->body.len>0)
493                 LM_ERR("\tevent=[%.*s]\n", msg->event->body.len, msg->event->body.s);
494         
495         if(reply_bad_event(msg)< 0)
496                 return -1;
497
498         return 0;
499
500 }
501
502