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