00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00032 #include <time.h>
00033
00034 #include "../../ut.h"
00035 #include "../../str.h"
00036 #include "../../mod_fix.h"
00037 #include "../../parser/parse_to.h"
00038 #include "../../parser/parse_uri.h"
00039 #include "../../parser/parse_expires.h"
00040 #include "../../parser/parse_event.h"
00041 #include "../../parser/parse_content.h"
00042 #include "../../lock_ops.h"
00043 #include "../../hashes.h"
00044 #include "../../lib/kcore/cmpapi.h"
00045 #include "../../lib/srdb1/db.h"
00046 #include "presence.h"
00047 #include "notify.h"
00048 #include "utils_func.h"
00049 #include "publish.h"
00050 #include "presentity.h"
00051 #include "../xcap_client/xcap_callbacks.h"
00052
00053 extern gen_lock_set_t* set;
00054
00055 static str pu_400a_rpl = str_init("Bad request");
00056 static str pu_400b_rpl = str_init("Invalid request");
00057 static str pu_500_rpl = str_init("Server Internal Error");
00058 static str pu_489_rpl = str_init("Bad Event");
00059
00060 static str str_doc_uri_col = str_init("doc_uri");
00061 static str str_doc_type_col = str_init("doc_type");
00062 static str str_doc_col = str_init("doc");
00063
00064 struct p_modif
00065 {
00066 presentity_t* p;
00067 str uri;
00068 };
00069
00070 void msg_presentity_clean(unsigned int ticks,void *param)
00071 {
00072 db_key_t db_keys[2], result_cols[4];
00073 db_val_t db_vals[2], *values;
00074 db_op_t db_ops[2] ;
00075 db1_res_t *result = NULL;
00076 db_row_t *rows;
00077 int n_db_cols = 0, n_result_cols = 0;
00078 int event_col, etag_col, user_col, domain_col;
00079 int i = 0, num_watchers = 0;
00080 presentity_t pres;
00081 str uri = {0, 0}, event, *rules_doc = NULL;
00082
00083 LM_DBG("cleaning expired presentity information\n");
00084 if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
00085 {
00086 LM_ERR("in use_table\n");
00087 return ;
00088 }
00089
00090 db_keys[n_db_cols] = &str_expires_col;
00091 db_ops[n_db_cols] = OP_LT;
00092 db_vals[n_db_cols].type = DB1_INT;
00093 db_vals[n_db_cols].nul = 0;
00094 db_vals[n_db_cols].val.int_val = (int)time(NULL);
00095 n_db_cols++;
00096
00097 db_keys[n_db_cols] = &str_expires_col;
00098 db_ops[n_db_cols] = OP_GT;
00099 db_vals[n_db_cols].type = DB1_INT;
00100 db_vals[n_db_cols].nul = 0;
00101 db_vals[n_db_cols].val.int_val = 0;
00102 n_db_cols++;
00103
00104 result_cols[user_col= n_result_cols++] = &str_username_col;
00105 result_cols[domain_col=n_result_cols++] = &str_domain_col;
00106 result_cols[etag_col=n_result_cols++] = &str_etag_col;
00107 result_cols[event_col=n_result_cols++] = &str_event_col;
00108
00109 static str query_str = str_init("username");
00110 if (db_fetch_query(&pa_dbf, pres_fetch_rows, pa_db, db_keys, db_ops,
00111 db_vals, result_cols, n_db_cols, n_result_cols,
00112 &query_str, &result) < 0)
00113 {
00114 LM_ERR("failed to query database for expired messages\n");
00115 goto delete_pres;
00116 }
00117
00118 if(result == NULL)
00119 {
00120 LM_ERR("bad result\n");
00121 return;
00122 }
00123
00124 LM_DBG("found n= %d expires messages\n ",result->n);
00125
00126 do {
00127 rows = RES_ROWS(result);
00128
00129 for(i = 0; i < RES_ROW_N(result); i++)
00130 {
00131 values = ROW_VALUES(&rows[i]);
00132 memset(&pres, 0, sizeof(presentity_t));
00133
00134 pres.user.s = (char *) VAL_STRING(&values[user_col]);
00135 pres.user.len = strlen(pres.user.s);
00136 pres.domain.s = (char *) VAL_STRING(&values[domain_col]);
00137 pres.domain.len = strlen(pres.domain.s);
00138 pres.etag.s = (char *) VAL_STRING(&values[etag_col]);
00139 pres.etag.len = strlen(pres.etag.s);
00140 event.s = (char *) VAL_STRING(&values[event_col]);
00141 event.len = strlen(event.s);
00142 pres.event= contains_event(&event, NULL);
00143 if(pres.event== NULL)
00144 {
00145 LM_ERR("event not found\n");
00146 goto error;
00147 }
00148
00149 if(uandd_to_uri(pres.user, pres.domain, &uri)< 0)
00150 {
00151 LM_ERR("constructing uri\n");
00152 goto error;
00153 }
00154
00155
00156 if(publ_cache_enabled && delete_phtable(&uri, pres.event->type)< 0)
00157 {
00158 LM_ERR("deleting from pres hash table\n");
00159 goto error;
00160 }
00161
00162 LM_DBG("found expired publish for [user]=%.*s [domanin]=%.*s\n",
00163 pres.user.len,pres.user.s, pres.domain.len, pres.domain.s);
00164
00165 if (pres_notifier_processes > 0)
00166 {
00167 if ((num_watchers = publ_notify_notifier(uri, pres.event)) < 0)
00168 {
00169 LM_ERR("Updating watcher records\n");
00170 goto error;
00171 }
00172
00173 if (num_watchers > 0)
00174 {
00175 if (mark_presentity_for_delete(&pres) < 0)
00176 {
00177 LM_ERR("Marking presentity\n");
00178 goto error;
00179 }
00180 }
00181 else
00182 {
00183 if (delete_presentity(&pres) < 0)
00184 {
00185 LM_ERR("Deleting presentity\n");
00186 goto error;
00187 }
00188 }
00189 }
00190 else
00191 {
00192 if(pres.event->get_rules_doc &&
00193 pres.event->get_rules_doc(&pres.user,
00194 &pres.domain,
00195 &rules_doc)< 0)
00196 {
00197 LM_ERR("getting rules doc\n");
00198 goto error;
00199 }
00200 if(publ_notify(&pres, uri, NULL, &pres.etag, rules_doc)< 0)
00201 {
00202 LM_ERR("sending Notify request\n");
00203 goto error;
00204 }
00205 if(rules_doc)
00206 {
00207 if(rules_doc->s)
00208 pkg_free(rules_doc->s);
00209 pkg_free(rules_doc);
00210 rules_doc= NULL;
00211 }
00212 }
00213
00214 pkg_free(uri.s);
00215 uri.s = NULL;
00216 }
00217 } while (db_fetch_next(&pa_dbf, pres_fetch_rows, pa_db, &result) == 1
00218 && RES_ROW_N(result) > 0);
00219
00220 pa_dbf.free_result(pa_db, result);
00221 result = NULL;
00222
00223 if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
00224 {
00225 LM_ERR("in use_table\n");
00226 goto error;
00227 }
00228
00229 if (pres_notifier_processes == 0)
00230 {
00231 delete_pres:
00232 if (pa_dbf.delete(pa_db, db_keys, db_ops, db_vals, n_db_cols) < 0)
00233 LM_ERR("failed to delete expired records from DB\n");
00234 }
00235
00236 return;
00237
00238 error:
00239 if(result)
00240 pa_dbf.free_result(pa_db, result);
00241 if(uri.s) pkg_free(uri.s);
00242 if(rules_doc)
00243 {
00244 if(rules_doc->s)
00245 pkg_free(rules_doc->s);
00246 pkg_free(rules_doc);
00247 }
00248
00249 return;
00250 }
00251
00256 int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
00257 {
00258 struct sip_uri puri;
00259 str body;
00260 int lexpire;
00261 presentity_t* presentity = 0;
00262 struct hdr_field* hdr;
00263 int found= 0, etag_gen = 0;
00264 str etag={0, 0};
00265 str* sender= NULL;
00266 static char buf[256];
00267 int buf_len= 255;
00268 pres_ev_t* event= NULL;
00269 str pres_user;
00270 str pres_domain;
00271 int reply_code;
00272 str reply_str;
00273 int sent_reply= 0;
00274 char* sphere= NULL;
00275
00276 reply_code= 500;
00277 reply_str= pu_500_rpl;
00278
00279 counter++;
00280 if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
00281 {
00282 LM_ERR("parsing headers\n");
00283 reply_code= 400;
00284 reply_str= pu_400a_rpl;
00285 goto error;
00286 }
00287 memset(&body, 0, sizeof(str));
00288
00289
00290
00291 if(msg->event && msg->event->body.len > 0)
00292 {
00293 if (!msg->event->parsed && (parse_event(msg->event) < 0))
00294 {
00295 LM_ERR("cannot parse Event header\n");
00296 reply_code= 400;
00297 reply_str= pu_400a_rpl;
00298 goto error;
00299 }
00300 }
00301 else
00302 goto unsupported_event;
00303
00304
00305 event= search_event((event_t*)msg->event->parsed);
00306 if(event== NULL)
00307 {
00308 goto unsupported_event;
00309 }
00310
00311
00312 hdr = msg->headers;
00313 while (hdr!= NULL)
00314 {
00315 if(cmp_hdrname_strzn(&hdr->name, "SIP-If-Match", 12)==0)
00316 {
00317 found = 1;
00318 break;
00319 }
00320 hdr = hdr->next;
00321 }
00322 if(found==0 )
00323 {
00324 LM_DBG("SIP-If-Match header not found\n");
00325 etag.s = generate_ETag(0);
00326 if(etag.s == NULL)
00327 {
00328 LM_ERR("when generating etag\n");
00329 goto error;
00330 }
00331 etag.len=(strlen(etag.s));
00332 etag_gen=1;
00333 LM_DBG("new etag = %.*s \n", etag.len, etag.s);
00334 }
00335 else
00336 {
00337 LM_DBG("SIP-If-Match header found\n");
00338 etag.s = (char*)pkg_malloc((hdr->body.len+ 1)* sizeof(char));
00339 if(etag.s== NULL)
00340 {
00341 ERR_MEM(PKG_MEM_STR);
00342 }
00343 memcpy(etag.s, hdr->body.s, hdr->body.len );
00344 etag.len = hdr->body.len;
00345 etag.s[ etag.len] = '\0';
00346 LM_DBG("existing etag = %.*s \n", etag.len, etag.s);
00347 }
00348
00349
00350 if(msg->expires && msg->expires->body.len > 0)
00351 {
00352 if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
00353 {
00354 LM_ERR("cannot parse Expires header\n");
00355 goto error;
00356 }
00357 lexpire = ((exp_body_t*)msg->expires->parsed)->val;
00358 LM_DBG("Expires header found, value= %d\n", lexpire);
00359
00360 }
00361 else
00362 {
00363 LM_DBG("'expires' not found; default=%d\n", event->default_expires);
00364 lexpire = event->default_expires;
00365 }
00366 if(lexpire > max_expires)
00367 lexpire = max_expires;
00368
00369
00370 if(parse_sip_msg_uri(msg)< 0)
00371 {
00372 LM_ERR("parsing Request URI\n");
00373 reply_code= 400;
00374 reply_str= pu_400a_rpl;
00375 goto error;
00376 }
00377 pres_user= msg->parsed_uri.user;
00378 pres_domain= msg->parsed_uri.host;
00379
00380 if (!msg->content_length)
00381 {
00382 LM_ERR("no Content-Length header found!\n");
00383 reply_code= 400;
00384 reply_str= pu_400a_rpl;
00385 goto error;
00386 }
00387
00388
00389 if ( get_content_length(msg) == 0 )
00390 {
00391 body.s = NULL;
00392 if (etag_gen)
00393 {
00394 LM_ERR("No E-Tag and no body found\n");
00395 reply_code= 400;
00396 reply_str= pu_400b_rpl;
00397 goto error;
00398 }
00399 }
00400 else
00401 {
00402 body.s=get_body(msg);
00403 if (body.s== NULL)
00404 {
00405 LM_ERR("cannot extract body\n");
00406 reply_code= 400;
00407 reply_str= pu_400a_rpl;
00408 goto error;
00409 }
00410 body.len= get_content_length( msg );
00411
00412 if(sphere_enable && event->evp->type == EVENT_PRESENCE &&
00413 get_content_type(msg)== SUBTYPE_PIDFXML)
00414 {
00415 sphere= extract_sphere(body);
00416 }
00417
00418 }
00419 memset(&puri, 0, sizeof(struct sip_uri));
00420 if(sender_uri)
00421 {
00422 sender=(str*)pkg_malloc(sizeof(str));
00423 if(sender== NULL)
00424 {
00425 ERR_MEM(PKG_MEM_STR);
00426 }
00427 if(pv_printf(msg, (pv_elem_t*)sender_uri, buf, &buf_len)<0)
00428 {
00429 LM_ERR("cannot print the format\n");
00430 goto error;
00431 }
00432 if(parse_uri(buf, buf_len, &puri)!=0)
00433 {
00434 LM_ERR("bad sender SIP address!\n");
00435 reply_code= 400;
00436 reply_str= pu_400a_rpl;
00437 goto error;
00438 }
00439 else
00440 {
00441 LM_DBG("using user id [%.*s]\n",buf_len,buf);
00442 }
00443 sender->s= buf;
00444 sender->len= buf_len;
00445 }
00446
00447 if(event->evs_publ_handl)
00448 {
00449 if(event->evs_publ_handl(msg)< 0)
00450 {
00451 LM_ERR("in event specific publish handling\n");
00452 goto error;
00453 }
00454 }
00455
00456
00457
00458
00459 presentity= new_presentity(&pres_domain, &pres_user, lexpire, event,
00460 &etag, sender);
00461 if(presentity== NULL)
00462 {
00463 LM_ERR("creating presentity structure\n");
00464 goto error;
00465 }
00466
00467
00468 if(update_presentity(msg, presentity, &body, etag_gen, &sent_reply, sphere) <0)
00469 {
00470 LM_ERR("when updating presentity\n");
00471 goto error;
00472 }
00473
00474 if(presentity)
00475 pkg_free(presentity);
00476 if(etag.s)
00477 pkg_free(etag.s);
00478 if(sender)
00479 pkg_free(sender);
00480 if(sphere)
00481 pkg_free(sphere);
00482
00483 return 1;
00484
00485 unsupported_event:
00486
00487 LM_WARN("Missing or unsupported event header field value\n");
00488
00489 if(msg->event && msg->event->body.s && msg->event->body.len>0)
00490 LM_ERR(" event=[%.*s]\n", msg->event->body.len, msg->event->body.s);
00491
00492 reply_code= BAD_EVENT_CODE;
00493 reply_str= pu_489_rpl;
00494
00495 error:
00496 if(sent_reply== 0)
00497 {
00498 if(send_error_reply(msg, reply_code, reply_str)< 0)
00499 {
00500 LM_ERR("failed to send error reply\n");
00501 }
00502 }
00503
00504 if(presentity)
00505 pkg_free(presentity);
00506 if(etag.s)
00507 pkg_free(etag.s);
00508 if(sender)
00509 pkg_free(sender);
00510 if(sphere)
00511 pkg_free(sphere);
00512
00513 return -1;
00514
00515 }
00516
00517 static int fetch_presentity(str furi, str *presentity)
00518 {
00519 db_key_t query_cols[2], result_cols[1];
00520 db_val_t query_vals[2], *row_vals;
00521 db1_res_t *result;
00522 db_row_t *row;
00523 int n_query_cols = 0, n_result_cols = 0;;
00524 char *tmp;
00525
00526 query_cols[n_query_cols] = &str_doc_uri_col;
00527 query_vals[n_query_cols].type = DB1_STR;
00528 query_vals[n_query_cols].nul = 0;
00529 query_vals[n_query_cols].val.str_val = furi;
00530 n_query_cols++;
00531
00532 query_cols[n_query_cols] = &str_doc_type_col;
00533 query_vals[n_query_cols].type = DB1_INT;
00534 query_vals[n_query_cols].nul = 0;
00535 query_vals[n_query_cols].val.int_val = PIDF_MANIPULATION;
00536 n_query_cols++;
00537
00538 result_cols[n_result_cols++] = &str_doc_col;
00539
00540 if (pres_xcap_dbf.use_table(pres_xcap_db, &pres_xcap_table) < 0)
00541 {
00542 LM_ERR("calling use_table()\n");
00543 return -1;
00544 }
00545
00546 if (pres_xcap_dbf.query(pres_xcap_db, query_cols, 0, query_vals, result_cols,
00547 n_query_cols, n_result_cols, 0, &result) < 0)
00548 {
00549 LM_ERR("calling query()\n");
00550 return -1;
00551 }
00552
00553 if (result == NULL)
00554 {
00555 LM_ERR("bad result\n");
00556 return -1;
00557 }
00558
00559 if (result->n <=0)
00560 {
00561 pres_xcap_dbf.free_result(pres_xcap_db, result);
00562 return 0;
00563 }
00564
00565 if (result->n > 1)
00566 {
00567 pres_xcap_dbf.free_result(pres_xcap_db, result);
00568 return -1;
00569 }
00570
00571 row = &result->rows[0];
00572 row_vals = ROW_VALUES(row);
00573
00574 tmp = (char *)row_vals[0].val.string_val;
00575 if (tmp == NULL)
00576 {
00577 LM_ERR("xcap document is empty\n");
00578 pres_xcap_dbf.free_result(pres_xcap_db, result);
00579 return -1;
00580 }
00581 presentity->len = strlen(tmp);
00582
00583 presentity->s = pkg_malloc(presentity->len * sizeof(char));
00584 if (presentity->s == NULL)
00585 {
00586 LM_ERR("allocating memory\n");
00587 pres_xcap_dbf.free_result(pres_xcap_db, result);
00588 return -1;
00589 }
00590 memcpy(presentity->s, tmp, presentity->len);
00591
00592 pres_xcap_dbf.free_result(pres_xcap_db, result);
00593 return 1;
00594 }
00595
00596 int pres_update_presentity(struct sip_msg *msg, char *puri, char *furi, char *fname)
00597 {
00598 int pres_result, ret = -1, new_t;
00599 char *sphere = NULL;
00600 str pres_uri, file_uri, filename, presentity, ev;
00601 pres_ev_t *event;
00602 presentity_t *pres = NULL;
00603 struct sip_uri parsed_uri;
00604
00605 if(fixup_get_svalue(msg, (gparam_p)puri, &pres_uri)!=0)
00606 {
00607 LM_ERR("invalid uri parameter");
00608 return -1;
00609 }
00610 if(fixup_get_svalue(msg, (gparam_p)furi, &file_uri)!=0)
00611 {
00612 LM_ERR("invalid file_uri parameter");
00613 return -1;
00614 }
00615 if(fixup_get_svalue(msg, (gparam_p)fname, &filename)!=0)
00616 {
00617 LM_ERR("invalid filename parameter");
00618 return -1;
00619 }
00620
00621 LM_INFO("Hard-state file %.*s (uri %.*s) updated for %.*s\n",
00622 filename.len, filename.s,
00623 file_uri.len, file_uri.s,
00624 pres_uri.len, pres_uri.s);
00625
00626 if (pres_integrated_xcap_server != 1)
00627 {
00628 LM_ERR("integrated XCAP server not configured\n");
00629 return -1;
00630 }
00631
00632 ev.s = "presence";
00633 ev.len = 8;
00634 event = contains_event(&ev, NULL);
00635 if (event == NULL)
00636 {
00637 LM_ERR("presence event not supported\n");
00638 return -1;
00639 }
00640
00641 if (parse_uri(pres_uri.s, pres_uri.len, &parsed_uri) < 0)
00642 {
00643 LM_ERR("bad presentity URI\n");
00644 return -1;
00645 }
00646
00647 pres_result = fetch_presentity(file_uri, &presentity);
00648 if (pres_result < 0)
00649 {
00650 LM_ERR("retrieving presentity\n");
00651 return -1;
00652 }
00653 else if (pres_result > 0)
00654 {
00655
00656 LM_DBG("INSERT/REPLACE\n");
00657 xmlDocPtr doc;
00658
00659 if (sphere_enable)
00660 sphere = extract_sphere(presentity);
00661
00662 doc = xmlParseMemory(presentity.s, presentity.len);
00663 if (doc == NULL)
00664 {
00665 LM_ERR("bad body format\n");
00666 xmlFreeDoc(doc);
00667 xmlCleanupParser();
00668 xmlMemoryDump();
00669 goto done;
00670 }
00671 xmlFreeDoc(doc);
00672 xmlCleanupParser();
00673 xmlMemoryDump();
00674
00675 new_t = 1;
00676 }
00677 else
00678 {
00679
00680 LM_DBG("DELETE\n");
00681 new_t = 0;
00682 }
00683
00684 pres = new_presentity(&parsed_uri.host, &parsed_uri.user, -1, event, &filename, NULL);
00685 if (pres == NULL)
00686 {
00687 LM_ERR("creating presentity structure\n");
00688 goto done;
00689 }
00690
00691 if (update_presentity(NULL, pres, &presentity, new_t, NULL, sphere) < 0)
00692 {
00693 LM_ERR("updating presentity\n");
00694 goto done;
00695 }
00696
00697 ret = 1;
00698
00699 done:
00700 if (pres) pkg_free(pres);
00701 if (sphere) pkg_free(sphere);
00702 if (presentity.s) pkg_free(presentity.s);
00703
00704 return ret;
00705 }