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