00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00041 #include <stdio.h>
00042 #include <string.h>
00043 #include <stdlib.h>
00044 #include <sys/types.h>
00045 #include <sys/ipc.h>
00046 #include <unistd.h>
00047 #include <fcntl.h>
00048 #include <time.h>
00049
00050 #include "../../lib/srdb1/db.h"
00051 #include "../../sr_module.h"
00052 #include "../../dprint.h"
00053 #include "../../error.h"
00054 #include "../../ut.h"
00055 #include "../../parser/parse_to.h"
00056 #include "../../parser/parse_uri.h"
00057 #include "../../parser/parse_content.h"
00058 #include "../../parser/parse_from.h"
00059 #include "../../mem/mem.h"
00060 #include "../../mem/shm_mem.h"
00061 #include "../../usr_avp.h"
00062 #include "../../modules/tm/tm_load.h"
00063 #include "../../modules/sl/sl.h"
00064 #include "../../pt.h"
00065 #include "../../lib/kmi/mi.h"
00066 #include "../../hashes.h"
00067 #include "../pua/hash.h"
00068 #include "presence.h"
00069 #include "publish.h"
00070 #include "subscribe.h"
00071 #include "event_list.h"
00072 #include "bind_presence.h"
00073 #include "notify.h"
00074 #include "../../mod_fix.h"
00075 #include "../../timer_proc.h"
00076
00077 MODULE_VERSION
00078
00079 #define S_TABLE_VERSION 3
00080 #define P_TABLE_VERSION 3
00081 #define ACTWATCH_TABLE_VERSION 11
00082 #define XCAP_TABLE_VERSION 4
00083
00084 char *log_buf = NULL;
00085 static int clean_period=100;
00086 static int db_update_period=100;
00087
00088
00089 db1_con_t *pa_db = NULL;
00090 db_func_t pa_dbf;
00091 db1_con_t *pres_xcap_db = NULL;
00092 db_func_t pres_xcap_dbf;
00093 str presentity_table= str_init("presentity");
00094 str active_watchers_table = str_init("active_watchers");
00095 str watchers_table= str_init("watchers");
00096 str pres_xcap_table= str_init("xcap");
00097
00098 int pres_fetch_rows = 500;
00099 int library_mode= 0;
00100 str server_address= {0, 0};
00101 evlist_t* EvList= NULL;
00102
00103
00104 char* to_tag_pref = "10";
00105
00106
00107 struct tm_binds tmb;
00108
00109 sl_api_t slb;
00110
00113 static int mod_init(void);
00114 static int child_init(int);
00115 static void destroy(void);
00116 int stored_pres_info(struct sip_msg* msg, char* pres_uri, char* s);
00117 static int fixup_presence(void** param, int param_no);
00118 static int fixup_subscribe(void** param, int param_no);
00119 static struct mi_root* mi_refreshWatchers(struct mi_root* cmd, void* param);
00120 static struct mi_root* mi_cleanup(struct mi_root* cmd, void* param);
00121 static int update_pw_dialogs(subs_t* subs, unsigned int hash_code,
00122 subs_t** subs_array);
00123 int update_watchers_status(str pres_uri, pres_ev_t* ev, str* rules_doc);
00124 static int mi_child_init(void);
00125 static int w_pres_auth_status(struct sip_msg* _msg, char* _sp1, char* _sp2);
00126 static int w_pres_refresh_watchers(struct sip_msg *msg, char *puri,
00127 char *pevent, char *ptype);
00128 static int w_pres_update_watchers(struct sip_msg *msg, char *puri,
00129 char *pevent);
00130 static int fixup_refresh_watchers(void** param, int param_no);
00131 static int fixup_update_watchers(void** param, int param_no);
00132 static int fixup_update_presentity(void** param, int param_no);
00133
00134 int counter =0;
00135 int pid = 0;
00136 char prefix='a';
00137 int startup_time=0;
00138 str db_url = {0, 0};
00139 str pres_xcap_db_url = {0, 0};
00140 int expires_offset = 0;
00141 int max_expires= 3600;
00142 int shtable_size= 9;
00143 shtable_t subs_htable= NULL;
00144 int subs_dbmode = WRITE_BACK;
00145 int sphere_enable= 0;
00146 int timeout_rm_subs = 1;
00147 int send_fast_notify = 1;
00148 int publ_cache_enabled = 1;
00149 int pres_waitn_time = 5;
00150 int pres_notifier_poll_rate = 10;
00151 int pres_notifier_processes = 1;
00152 int pres_integrated_xcap_server = 0;
00153
00154 int *pres_notifier_id = NULL;
00155
00156 int phtable_size= 9;
00157 phtable_t* pres_htable=NULL;
00158
00159 static cmd_export_t cmds[]=
00160 {
00161 {"handle_publish", (cmd_function)handle_publish, 0,
00162 fixup_presence,0, REQUEST_ROUTE},
00163 {"handle_publish", (cmd_function)handle_publish, 1,
00164 fixup_presence, 0, REQUEST_ROUTE},
00165 {"handle_subscribe", (cmd_function)handle_subscribe0, 0,
00166 fixup_subscribe,0, REQUEST_ROUTE},
00167 {"handle_subscribe", (cmd_function)w_handle_subscribe, 1,
00168 fixup_subscribe,0, REQUEST_ROUTE},
00169 {"pres_auth_status", (cmd_function)w_pres_auth_status, 2,
00170 fixup_pvar_pvar, fixup_free_pvar_pvar, REQUEST_ROUTE},
00171 {"pres_refresh_watchers", (cmd_function)w_pres_refresh_watchers, 3,
00172 fixup_refresh_watchers, 0, ANY_ROUTE},
00173 {"pres_update_watchers", (cmd_function)w_pres_update_watchers, 2,
00174 fixup_update_watchers, 0, ANY_ROUTE},
00175 {"pres_update_presentity", (cmd_function)pres_update_presentity, 3,
00176 fixup_update_presentity, 0, ANY_ROUTE},
00177 {"bind_presence", (cmd_function)bind_presence, 1,
00178 0, 0, 0},
00179 { 0, 0, 0, 0, 0, 0}
00180 };
00181
00182 static param_export_t params[]={
00183 { "db_url", STR_PARAM, &db_url.s},
00184 { "xcap_db_url", STR_PARAM, &pres_xcap_db_url.s},
00185 { "presentity_table", STR_PARAM, &presentity_table.s},
00186 { "active_watchers_table", STR_PARAM, &active_watchers_table.s},
00187 { "watchers_table", STR_PARAM, &watchers_table.s},
00188 { "xcap_table", STR_PARAM, &pres_xcap_table.s},
00189 { "clean_period", INT_PARAM, &clean_period },
00190 { "db_update_period", INT_PARAM, &db_update_period },
00191 { "waitn_time", INT_PARAM, &pres_waitn_time },
00192 { "notifier_poll_rate", INT_PARAM, &pres_notifier_poll_rate },
00193 { "notifier_processes", INT_PARAM, &pres_notifier_processes },
00194 { "to_tag_pref", STR_PARAM, &to_tag_pref },
00195 { "expires_offset", INT_PARAM, &expires_offset },
00196 { "max_expires", INT_PARAM, &max_expires },
00197 { "server_address", STR_PARAM, &server_address.s},
00198 { "subs_htable_size", INT_PARAM, &shtable_size},
00199 { "pres_htable_size", INT_PARAM, &phtable_size},
00200 { "subs_db_mode", INT_PARAM, &subs_dbmode},
00201 { "publ_cache", INT_PARAM, &publ_cache_enabled},
00202 { "enable_sphere_check", INT_PARAM, &sphere_enable},
00203 { "timeout_rm_subs", INT_PARAM, &timeout_rm_subs},
00204 { "send_fast_notify", INT_PARAM, &send_fast_notify},
00205 { "fetch_rows", INT_PARAM, &pres_fetch_rows},
00206 { "integrated_xcap_server", INT_PARAM, &pres_integrated_xcap_server},
00207 {0,0,0}
00208 };
00209
00210 static mi_export_t mi_cmds[] = {
00211 { "refreshWatchers", mi_refreshWatchers, 0, 0, mi_child_init},
00212 { "cleanup", mi_cleanup, 0, 0, mi_child_init},
00213 { 0, 0, 0, 0, 0}
00214 };
00215
00217 struct module_exports exports= {
00218 "presence",
00219 DEFAULT_DLFLAGS,
00220 cmds,
00221 params,
00222 0,
00223 mi_cmds,
00224 0,
00225 0,
00226 mod_init,
00227 0,
00228 (destroy_function) destroy,
00229 child_init
00230 };
00231
00235 static int mod_init(void)
00236 {
00237 if(register_mi_mod(exports.name, mi_cmds)!=0)
00238 {
00239 LM_ERR("failed to register MI commands\n");
00240 return -1;
00241 }
00242
00243 db_url.len = db_url.s ? strlen(db_url.s) : 0;
00244 LM_DBG("db_url=%s/%d/%p\n", ZSW(db_url.s), db_url.len,db_url.s);
00245 presentity_table.len = strlen(presentity_table.s);
00246 active_watchers_table.len = strlen(active_watchers_table.s);
00247 watchers_table.len = strlen(watchers_table.s);
00248
00249 if(pres_integrated_xcap_server == 1)
00250 {
00251 pres_xcap_db_url.s = pres_xcap_db_url.s ? pres_xcap_db_url.s : db_url.s;
00252 pres_xcap_db_url.len = strlen(pres_xcap_db_url.s);
00253 pres_xcap_table.len = strlen(pres_xcap_table.s);
00254 }
00255
00256 if(db_url.s== NULL)
00257 library_mode= 1;
00258 else if(pres_integrated_xcap_server == 1)
00259 {
00260 pres_xcap_db_url.s = pres_xcap_db_url.s ? pres_xcap_db_url.s : db_url.s;
00261 pres_xcap_db_url.len = strlen(pres_xcap_db_url.s);
00262 pres_xcap_table.len = strlen(pres_xcap_table.s);
00263 }
00264
00265 EvList= init_evlist();
00266 if(!EvList){
00267 LM_ERR("unsuccessful initialize event list\n");
00268 return -1;
00269 }
00270
00271 if(library_mode== 1)
00272 {
00273 LM_DBG("Presence module used for API library purpose only\n");
00274 return 0;
00275 }
00276
00277 if(expires_offset<0)
00278 expires_offset = 0;
00279
00280 if(to_tag_pref==NULL || strlen(to_tag_pref)==0)
00281 to_tag_pref="10";
00282
00283 if(max_expires<= 0)
00284 max_expires = 3600;
00285
00286 if(server_address.s== NULL)
00287 LM_DBG("server_address parameter not set in configuration file\n");
00288
00289 if(server_address.s)
00290 server_address.len= strlen(server_address.s);
00291 else
00292 server_address.len= 0;
00293
00294
00295 if (sl_load_api(&slb)!=0) {
00296 LM_ERR("cannot bind to SL API\n");
00297 return -1;
00298 }
00299
00300
00301 if(load_tm_api(&tmb)==-1)
00302 {
00303 LM_ERR("Can't load tm functions. Module TM not loaded?\n");
00304 return -1;
00305 }
00306
00307 if(db_url.s== NULL)
00308 {
00309 LM_ERR("database url not set!\n");
00310 return -1;
00311 }
00312
00313
00314 if (db_bind_mod(&db_url, &pa_dbf))
00315 {
00316 LM_ERR("Database module not found\n");
00317 return -1;
00318 }
00319
00320 if (!DB_CAPABILITY(pa_dbf, DB_CAP_ALL))
00321 {
00322 LM_ERR("Database module does not implement all functions"
00323 " needed by presence module\n");
00324 return -1;
00325 }
00326
00327 pa_db = pa_dbf.init(&db_url);
00328 if (!pa_db)
00329 {
00330 LM_ERR("Connection to database failed\n");
00331 return -1;
00332 }
00333
00334 if((db_check_table_version(&pa_dbf, pa_db, &presentity_table, P_TABLE_VERSION) < 0) ||
00335 (db_check_table_version(&pa_dbf, pa_db, &watchers_table, S_TABLE_VERSION) < 0)) {
00336 LM_ERR("error during table version check\n");
00337 return -1;
00338 }
00339 if(subs_dbmode != NO_DB &&
00340 db_check_table_version(&pa_dbf, pa_db, &active_watchers_table, ACTWATCH_TABLE_VERSION) < 0) {
00341 LM_ERR("wrong table version for %s\n", active_watchers_table.s);
00342 return -1;
00343 }
00344
00345 if (pres_integrated_xcap_server == 1)
00346 {
00347 if(pres_xcap_db_url.s== NULL)
00348 {
00349 LM_ERR("xcap database url not set!\n");
00350 return -1;
00351 }
00352
00353 if (db_bind_mod(&pres_xcap_db_url, &pres_xcap_dbf))
00354 {
00355 LM_ERR("Database module not found\n");
00356 return -1;
00357 }
00358
00359 if (!DB_CAPABILITY(pres_xcap_dbf, DB_CAP_ALL))
00360 {
00361 LM_ERR("Database module does not implement all functions"
00362 " needed by presence module\n");
00363 return -1;
00364 }
00365
00366 pres_xcap_db = pres_xcap_dbf.init(&pres_xcap_db_url);
00367 if (!pres_xcap_db)
00368 {
00369 LM_ERR("Connection to database failed\n");
00370 return -1;
00371 }
00372
00373 if(db_check_table_version(&pres_xcap_dbf, pres_xcap_db, &pres_xcap_table, XCAP_TABLE_VERSION) < 0) {
00374 LM_ERR("error during table version check\n");
00375 return -1;
00376 }
00377 }
00378
00379 if(subs_dbmode != DB_ONLY) {
00380 if(shtable_size< 1)
00381 shtable_size= 512;
00382 else
00383 shtable_size= 1<< shtable_size;
00384
00385 subs_htable= new_shtable(shtable_size);
00386 if(subs_htable== NULL)
00387 {
00388 LM_ERR(" initializing subscribe hash table\n");
00389 return -1;
00390 }
00391 if(restore_db_subs()< 0)
00392 {
00393 LM_ERR("restoring subscribe info from database\n");
00394 return -1;
00395 }
00396 }
00397
00398 if(publ_cache_enabled) {
00399 if(phtable_size< 1)
00400 phtable_size= 256;
00401 else
00402 phtable_size= 1<< phtable_size;
00403
00404 pres_htable= new_phtable();
00405 if(pres_htable== NULL)
00406 {
00407 LM_ERR("initializing presentity hash table\n");
00408 return -1;
00409 }
00410
00411 if(pres_htable_restore()< 0)
00412 {
00413 LM_ERR("filling in presentity hash table from database\n");
00414 return -1;
00415 }
00416 }
00417
00418 startup_time = (int) time(NULL);
00419 if(clean_period>0)
00420 {
00421 register_timer(msg_presentity_clean, 0, clean_period);
00422 register_timer(msg_watchers_clean, 0, clean_period);
00423 }
00424
00425 if(db_update_period>0)
00426 register_timer(timer_db_update, 0, db_update_period);
00427
00428 if (pres_waitn_time <= 0)
00429 pres_waitn_time = 5;
00430
00431 if (pres_notifier_poll_rate <= 0)
00432 pres_notifier_poll_rate = 10;
00433
00434 if (pres_notifier_processes < 0 || subs_dbmode != DB_ONLY)
00435 pres_notifier_processes = 0;
00436
00437 if (pres_notifier_processes > 0)
00438 {
00439 if ((pres_notifier_id = shm_malloc(sizeof(int) * pres_notifier_processes)) == NULL)
00440 {
00441 LM_ERR("allocating shared memory\n");
00442 return -1;
00443 }
00444
00445 register_basic_timers(pres_notifier_processes);
00446 }
00447
00448 pa_dbf.close(pa_db);
00449 pa_db = NULL;
00450
00451 if (pres_integrated_xcap_server == 1)
00452 {
00453 pres_xcap_dbf.close(pres_xcap_db);
00454 pres_xcap_db = NULL;
00455 }
00456
00457 return 0;
00458 }
00459
00463 static int child_init(int rank)
00464 {
00465 if (rank==PROC_INIT || rank==PROC_TCP_MAIN)
00466 return 0;
00467
00468 if (rank == PROC_MAIN)
00469 {
00470 int i;
00471
00472 for (i = 0; i < pres_notifier_processes; i++)
00473 {
00474 char tmp[21];
00475 snprintf(tmp, 21, "PRESENCE NOTIFIER %d", i);
00476 pres_notifier_id[i] = i;
00477
00478 if (fork_basic_utimer(PROC_TIMER, tmp, 1,
00479 pres_timer_send_notify,
00480 &pres_notifier_id[i],
00481 1000000/pres_notifier_poll_rate) < 0)
00482 {
00483 LM_ERR("Failed to start PRESENCE NOTIFIER %d\n", i);
00484 return -1;
00485 }
00486 }
00487
00488 return 0;
00489 }
00490
00491 pid = my_pid();
00492
00493 if(library_mode)
00494 return 0;
00495
00496 if (pa_dbf.init==0)
00497 {
00498 LM_CRIT("child_init: database not bound\n");
00499 return -1;
00500 }
00501
00502
00503 if (pres_notifier_processes > 0 && pa_dbf.init2)
00504 pa_db = pa_dbf.init2(&db_url, DB_POOLING_NONE);
00505 else
00506 pa_db = pa_dbf.init(&db_url);
00507 if (!pa_db)
00508 {
00509 LM_ERR("child %d: unsuccessful connecting to database\n", rank);
00510 return -1;
00511 }
00512
00513 if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
00514 {
00515 LM_ERR( "child %d:unsuccessful use_table presentity_table\n", rank);
00516 return -1;
00517 }
00518
00519 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
00520 {
00521 LM_ERR( "child %d:unsuccessful use_table active_watchers_table\n",
00522 rank);
00523 return -1;
00524 }
00525
00526 if (pa_dbf.use_table(pa_db, &watchers_table) < 0)
00527 {
00528 LM_ERR( "child %d:unsuccessful use_table watchers_table\n", rank);
00529 return -1;
00530 }
00531
00532 if (pres_integrated_xcap_server == 1)
00533 {
00534 if (pres_xcap_dbf.init==0)
00535 {
00536 LM_CRIT("child_init: database not bound\n");
00537 return -1;
00538 }
00539 if (pres_xcap_db)
00540 return 0;
00541 pres_xcap_db = pres_xcap_dbf.init(&pres_xcap_db_url);
00542 if (!pres_xcap_db)
00543 {
00544 LM_ERR("child %d: unsuccessful connecting to database\n", rank);
00545 return -1;
00546 }
00547
00548 if (pres_xcap_dbf.use_table(pres_xcap_db, &pres_xcap_table) < 0)
00549 {
00550 LM_ERR( "child %d:unsuccessful use_table xcap_table\n", rank);
00551 return -1;
00552 }
00553 }
00554
00555 LM_DBG("child %d: Database connection opened successfully\n", rank);
00556
00557 return 0;
00558 }
00559
00560 static int mi_child_init(void)
00561 {
00562 if(library_mode)
00563 return 0;
00564
00565 if (pa_dbf.init==0)
00566 {
00567 LM_CRIT("database not bound\n");
00568 return -1;
00569 }
00570
00571
00572 if (pres_notifier_processes > 0 && pa_dbf.init2)
00573 pa_db = pa_dbf.init2(&db_url, DB_POOLING_NONE);
00574 else
00575 pa_db = pa_dbf.init(&db_url);
00576 if (!pa_db)
00577 {
00578 LM_ERR("connecting database\n");
00579 return -1;
00580 }
00581
00582 if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
00583 {
00584 LM_ERR( "unsuccessful use_table presentity_table\n");
00585 return -1;
00586 }
00587
00588 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
00589 {
00590 LM_ERR( "unsuccessful use_table active_watchers_table\n");
00591 return -1;
00592 }
00593
00594 if (pa_dbf.use_table(pa_db, &watchers_table) < 0)
00595 {
00596 LM_ERR( "unsuccessful use_table watchers_table\n");
00597 return -1;
00598 }
00599
00600 if (pres_integrated_xcap_server == 1)
00601 {
00602 if (pres_xcap_dbf.init==0)
00603 {
00604 LM_CRIT("database not bound\n");
00605 return -1;
00606 }
00607 if (pres_xcap_db)
00608 return 0;
00609 pres_xcap_db = pres_xcap_dbf.init(&db_url);
00610 if (!pres_xcap_db)
00611 {
00612 LM_ERR("connecting database\n");
00613 return -1;
00614 }
00615
00616 if (pres_xcap_dbf.use_table(pres_xcap_db, &pres_xcap_table) < 0)
00617 {
00618 LM_ERR( "unsuccessful use_table xcap_table\n");
00619 return -1;
00620 }
00621 }
00622
00623 LM_DBG("Database connection opened successfully\n");
00624 return 0;
00625 }
00626
00627
00628
00629
00630
00631 static void destroy(void)
00632 {
00633 if(subs_htable && subs_dbmode == WRITE_BACK) {
00634
00635 pa_db = pa_dbf.init(&db_url);
00636 if (!pa_db) {
00637 LM_ERR("mod_destroy: unsuccessful connecting to database\n");
00638 } else
00639 timer_db_update(0, 0);
00640 }
00641
00642 if(subs_htable)
00643 destroy_shtable(subs_htable, shtable_size);
00644
00645 if(pres_htable)
00646 destroy_phtable();
00647
00648 if(pa_db && pa_dbf.close)
00649 pa_dbf.close(pa_db);
00650
00651 if(pres_xcap_db && pres_xcap_dbf.close)
00652 pres_xcap_dbf.close(pres_xcap_db);
00653
00654 if (pres_notifier_id != NULL)
00655 shm_free(pres_notifier_id);
00656
00657 destroy_evlist();
00658 }
00659
00660 static int fixup_presence(void** param, int param_no)
00661 {
00662 pv_elem_t *model;
00663 str s;
00664
00665 if(library_mode)
00666 {
00667 LM_ERR("Bad config - you can not call 'handle_publish' function"
00668 " (db_url not set)\n");
00669 return -1;
00670 }
00671 if(param_no== 0)
00672 return 0;
00673
00674 if(*param)
00675 {
00676 s.s = (char*)(*param); s.len = strlen(s.s);
00677 if(pv_parse_format(&s, &model)<0)
00678 {
00679 LM_ERR( "wrong format[%s]\n",(char*)(*param));
00680 return E_UNSPEC;
00681 }
00682
00683 *param = (void*)model;
00684 return 0;
00685 }
00686 LM_ERR( "null format\n");
00687 return E_UNSPEC;
00688 }
00689
00690 static int fixup_subscribe(void** param, int param_no)
00691 {
00692
00693 if(library_mode)
00694 {
00695 LM_ERR("Bad config - you can not call 'handle_subscribe' function"
00696 " (db_url not set)\n");
00697 return -1;
00698 }
00699 if (param_no == 1) {
00700 return fixup_spve_null(param, 1);
00701 }
00702 return 0;
00703 }
00704
00705 int pres_refresh_watchers(str *pres, str *event, int type)
00706 {
00707 pres_ev_t *ev;
00708 struct sip_uri uri;
00709 str *rules_doc= NULL;
00710 int result;
00711
00712 ev= contains_event(event, NULL);
00713 if(ev==NULL)
00714 {
00715 LM_ERR("wrong event parameter\n");
00716 return -1;
00717 }
00718
00719 if(type==0)
00720 {
00721
00722 if(ev->get_rules_doc==NULL)
00723 {
00724 LM_ERR("wrong request for a refresh watchers authorization status"
00725 "for an event that does not require authorization\n");
00726 goto error;
00727 }
00728
00729 if(parse_uri(pres->s, pres->len, &uri)<0)
00730 {
00731 LM_ERR("parsing uri [%.*s]\n", pres->len, pres->s);
00732 goto error;
00733 }
00734
00735 result= ev->get_rules_doc(&uri.user, &uri.host, &rules_doc);
00736 if(result<0 || rules_doc==NULL || rules_doc->s==NULL)
00737 {
00738 LM_ERR("no rules doc found for the user\n");
00739 goto error;
00740 }
00741
00742 if(update_watchers_status(*pres, ev, rules_doc)<0)
00743 {
00744 LM_ERR("failed to update watchers\n");
00745 goto error;
00746 }
00747
00748 pkg_free(rules_doc->s);
00749 pkg_free(rules_doc);
00750 rules_doc = NULL;
00751
00752 } else {
00753
00754 if(query_db_notify(pres, ev, NULL)< 0)
00755 {
00756 LM_ERR("sending Notify requests\n");
00757 goto error;
00758 }
00759
00760 }
00761 return 0;
00762
00763 error:
00764 if(rules_doc)
00765 {
00766 if(rules_doc->s)
00767 pkg_free(rules_doc->s);
00768 pkg_free(rules_doc);
00769 }
00770 return -1;
00771 }
00772
00781 static struct mi_root* mi_refreshWatchers(struct mi_root* cmd, void* param)
00782 {
00783 struct mi_node* node= NULL;
00784 str pres_uri, event;
00785 unsigned int refresh_type;
00786
00787 LM_DBG("start\n");
00788
00789 node = cmd->node.kids;
00790 if(node == NULL)
00791 return 0;
00792
00793
00794 pres_uri = node->value;
00795 if(pres_uri.s == NULL || pres_uri.len== 0)
00796 {
00797 LM_ERR( "empty uri\n");
00798 return init_mi_tree(404, "Empty presentity URI", 20);
00799 }
00800
00801 node = node->next;
00802 if(node == NULL)
00803 return 0;
00804 event= node->value;
00805 if(event.s== NULL || event.len== 0)
00806 {
00807 LM_ERR( "empty event parameter\n");
00808 return init_mi_tree(400, "Empty event parameter", 21);
00809 }
00810 LM_DBG("event '%.*s'\n", event.len, event.s);
00811
00812 node = node->next;
00813 if(node == NULL)
00814 return 0;
00815 if(node->value.s== NULL || node->value.len== 0)
00816 {
00817 LM_ERR( "empty refresh type parameter\n");
00818 return init_mi_tree(400, "Empty refresh type parameter", 28);
00819 }
00820 if(str2int(&node->value, &refresh_type)< 0)
00821 {
00822 LM_ERR("converting string to int\n");
00823 goto error;
00824 }
00825
00826 if(node->next!= NULL)
00827 {
00828 LM_ERR( "Too many parameters\n");
00829 return init_mi_tree(400, "Too many parameters", 19);
00830 }
00831
00832 if(pres_refresh_watchers(&pres_uri, &event, refresh_type)<0)
00833 return 0;
00834
00835 return init_mi_tree(200, "OK", 2);
00836
00837 error:
00838 return 0;
00839 }
00840
00841
00842
00843
00844
00845 static struct mi_root* mi_cleanup(struct mi_root* cmd, void* param)
00846 {
00847 LM_DBG("mi_cleanup:start\n");
00848
00849 (void)msg_watchers_clean(0,0);
00850 (void)msg_presentity_clean(0,0);
00851 (void)timer_db_update(0,0);
00852
00853 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00854 }
00855
00856 int pres_update_status(subs_t subs, str reason, db_key_t* query_cols,
00857 db_val_t* query_vals, int n_query_cols, subs_t** subs_array)
00858 {
00859 db_key_t update_cols[5];
00860 db_val_t update_vals[5];
00861 int n_update_cols= 0;
00862 int u_status_col, u_reason_col, q_wuser_col, q_wdomain_col;
00863 int status;
00864 query_cols[q_wuser_col=n_query_cols]= &str_watcher_username_col;
00865 query_vals[n_query_cols].nul= 0;
00866 query_vals[n_query_cols].type= DB1_STR;
00867 n_query_cols++;
00868
00869 query_cols[q_wdomain_col=n_query_cols]= &str_watcher_domain_col;
00870 query_vals[n_query_cols].nul= 0;
00871 query_vals[n_query_cols].type= DB1_STR;
00872 n_query_cols++;
00873
00874 update_cols[u_status_col= n_update_cols]= &str_status_col;
00875 update_vals[u_status_col].nul= 0;
00876 update_vals[u_status_col].type= DB1_INT;
00877 n_update_cols++;
00878
00879 update_cols[u_reason_col= n_update_cols]= &str_reason_col;
00880 update_vals[u_reason_col].nul= 0;
00881 update_vals[u_reason_col].type= DB1_STR;
00882 n_update_cols++;
00883
00884 status= subs.status;
00885 if(subs.event->get_auth_status(&subs)< 0)
00886 {
00887 LM_ERR( "getting status from rules document\n");
00888 return -1;
00889 }
00890 LM_DBG("subs.status= %d\n", subs.status);
00891 if(get_status_str(subs.status)== NULL)
00892 {
00893 LM_ERR("wrong status: %d\n", subs.status);
00894 return -1;
00895 }
00896
00897 if(subs.status!= status || reason.len!= subs.reason.len ||
00898 (reason.s && subs.reason.s && strncmp(reason.s, subs.reason.s,
00899 reason.len)))
00900 {
00901
00902 query_vals[q_wuser_col].val.str_val= subs.watcher_user;
00903 query_vals[q_wdomain_col].val.str_val= subs.watcher_domain;
00904
00905
00906 if(subs.status!=status && status==ACTIVE_STATUS)
00907 {
00908 subs.status = TERMINATED_STATUS;
00909 subs.reason.s = get_status_str(TERMINATED_STATUS);
00910 subs.reason.len = strlen(subs.reason.s);
00911 }
00912
00913 update_vals[u_status_col].val.int_val= subs.status;
00914 update_vals[u_reason_col].val.str_val= subs.reason;
00915
00916 if (pa_dbf.use_table(pa_db, &watchers_table) < 0)
00917 {
00918 LM_ERR( "in use_table\n");
00919 return -1;
00920 }
00921
00922 if(pa_dbf.update(pa_db, query_cols, 0, query_vals, update_cols,
00923 update_vals, n_query_cols, n_update_cols)< 0)
00924 {
00925 LM_ERR( "in sql update\n");
00926 return -1;
00927 }
00928
00929
00930 if(update_pw_dialogs(&subs, subs.db_flag, subs_array)< 0)
00931 {
00932 LM_ERR( "extracting dialogs from [watcher]=%.*s@%.*s to"
00933 " [presentity]=%.*s\n", subs.watcher_user.len, subs.watcher_user.s,
00934 subs.watcher_domain.len, subs.watcher_domain.s, subs.pres_uri.len,
00935 subs.pres_uri.s);
00936 return -1;
00937 }
00938 }
00939 return 0;
00940 }
00941
00942 int pres_db_delete_status(subs_t* s)
00943 {
00944 int n_query_cols= 0;
00945 db_key_t query_cols[5];
00946 db_val_t query_vals[5];
00947
00948 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
00949 {
00950 LM_ERR("sql use table failed\n");
00951 return -1;
00952 }
00953
00954 query_cols[n_query_cols]= &str_event_col;
00955 query_vals[n_query_cols].nul= 0;
00956 query_vals[n_query_cols].type= DB1_STR;
00957 query_vals[n_query_cols].val.str_val= s->event->name ;
00958 n_query_cols++;
00959
00960 query_cols[n_query_cols]= &str_presentity_uri_col;
00961 query_vals[n_query_cols].nul= 0;
00962 query_vals[n_query_cols].type= DB1_STR;
00963 query_vals[n_query_cols].val.str_val= s->pres_uri;
00964 n_query_cols++;
00965
00966 query_cols[n_query_cols]= &str_watcher_username_col;
00967 query_vals[n_query_cols].nul= 0;
00968 query_vals[n_query_cols].type= DB1_STR;
00969 query_vals[n_query_cols].val.str_val= s->watcher_user;
00970 n_query_cols++;
00971
00972 query_cols[n_query_cols]= &str_watcher_domain_col;
00973 query_vals[n_query_cols].nul= 0;
00974 query_vals[n_query_cols].type= DB1_STR;
00975 query_vals[n_query_cols].val.str_val= s->watcher_domain;
00976 n_query_cols++;
00977
00978 if(pa_dbf.delete(pa_db, query_cols, 0, query_vals, n_query_cols)< 0)
00979 {
00980 LM_ERR("sql delete failed\n");
00981 return -1;
00982 }
00983 return 0;
00984
00985 }
00986
00987 int update_watchers_status(str pres_uri, pres_ev_t* ev, str* rules_doc)
00988 {
00989 subs_t subs;
00990 db_key_t query_cols[6], result_cols[5];
00991 db_val_t query_vals[6];
00992 int n_result_cols= 0, n_query_cols = 0;
00993 db1_res_t* result= NULL;
00994 db_row_t *row;
00995 db_val_t *row_vals ;
00996 int i;
00997 str w_user, w_domain, reason= {0, 0};
00998 unsigned int status;
00999 int status_col, w_user_col, w_domain_col, reason_col;
01000 subs_t* subs_array= NULL,* s;
01001 unsigned int hash_code;
01002 int err_ret= -1;
01003 int n= 0;
01004
01005 typedef struct ws
01006 {
01007 int status;
01008 str reason;
01009 str w_user;
01010 str w_domain;
01011 }ws_t;
01012 ws_t* ws_list= NULL;
01013
01014 LM_DBG("start\n");
01015
01016 if(ev->content_type.s== NULL)
01017 {
01018 ev= contains_event(&ev->name, NULL);
01019 if(ev== NULL)
01020 {
01021 LM_ERR("wrong event parameter\n");
01022 return 0;
01023 }
01024 }
01025
01026 subs.pres_uri= pres_uri;
01027 subs.event= ev;
01028 subs.auth_rules_doc= rules_doc;
01029
01030
01031 query_cols[n_query_cols]= &str_presentity_uri_col;
01032 query_vals[n_query_cols].nul= 0;
01033 query_vals[n_query_cols].type= DB1_STR;
01034 query_vals[n_query_cols].val.str_val= pres_uri;
01035 n_query_cols++;
01036
01037 query_cols[n_query_cols]= &str_event_col;
01038 query_vals[n_query_cols].nul= 0;
01039 query_vals[n_query_cols].type= DB1_STR;
01040 query_vals[n_query_cols].val.str_val= ev->name;
01041 n_query_cols++;
01042
01043 result_cols[status_col= n_result_cols++]= &str_status_col;
01044 result_cols[reason_col= n_result_cols++]= &str_reason_col;
01045 result_cols[w_user_col= n_result_cols++]= &str_watcher_username_col;
01046 result_cols[w_domain_col= n_result_cols++]= &str_watcher_domain_col;
01047
01048 if (pa_dbf.use_table(pa_db, &watchers_table) < 0)
01049 {
01050 LM_ERR( "in use_table\n");
01051 goto done;
01052 }
01053
01054 if(pa_dbf.query(pa_db, query_cols, 0, query_vals, result_cols,n_query_cols,
01055 n_result_cols, 0, &result)< 0)
01056 {
01057 LM_ERR( "in sql query\n");
01058 goto done;
01059 }
01060 if(result== NULL)
01061 return 0;
01062
01063 if(result->n<= 0)
01064 {
01065 err_ret= 0;
01066 goto done;
01067 }
01068
01069 LM_DBG("found %d record-uri in watchers_table\n", result->n);
01070 hash_code= core_hash(&pres_uri, &ev->name, shtable_size);
01071 subs.db_flag= hash_code;
01072
01073
01074 if(sphere_enable)
01075 {
01076 n= result->n;
01077 ws_list= (ws_t*)pkg_malloc(n * sizeof(ws_t));
01078 if(ws_list== NULL)
01079 {
01080 LM_ERR("No more private memory\n");
01081 goto done;
01082 }
01083 memset(ws_list, 0, n * sizeof(ws_t));
01084
01085 for(i= 0; i< result->n ; i++)
01086 {
01087 row= &result->rows[i];
01088 row_vals = ROW_VALUES(row);
01089
01090 status= row_vals[status_col].val.int_val;
01091
01092 reason.s= (char*)row_vals[reason_col].val.string_val;
01093 reason.len= reason.s?strlen(reason.s):0;
01094
01095 w_user.s= (char*)row_vals[w_user_col].val.string_val;
01096 w_user.len= strlen(w_user.s);
01097
01098 w_domain.s= (char*)row_vals[w_domain_col].val.string_val;
01099 w_domain.len= strlen(w_domain.s);
01100
01101 if(reason.len)
01102 {
01103 ws_list[i].reason.s = (char*)pkg_malloc(reason.len* sizeof(char));
01104 if(ws_list[i].reason.s== NULL)
01105 {
01106 LM_ERR("No more private memory\n");
01107 goto done;
01108 }
01109 memcpy(ws_list[i].reason.s, reason.s, reason.len);
01110 ws_list[i].reason.len= reason.len;
01111 }
01112 else
01113 ws_list[i].reason.s= NULL;
01114
01115 ws_list[i].w_user.s = (char*)pkg_malloc(w_user.len* sizeof(char));
01116 if(ws_list[i].w_user.s== NULL)
01117 {
01118 LM_ERR("No more private memory\n");
01119 goto done;
01120
01121 }
01122 memcpy(ws_list[i].w_user.s, w_user.s, w_user.len);
01123 ws_list[i].w_user.len= w_user.len;
01124
01125 ws_list[i].w_domain.s = (char*)pkg_malloc(w_domain.len* sizeof(char));
01126 if(ws_list[i].w_domain.s== NULL)
01127 {
01128 LM_ERR("No more private memory\n");
01129 goto done;
01130 }
01131 memcpy(ws_list[i].w_domain.s, w_domain.s, w_domain.len);
01132 ws_list[i].w_domain.len= w_domain.len;
01133
01134 ws_list[i].status= status;
01135 }
01136
01137 pa_dbf.free_result(pa_db, result);
01138 result= NULL;
01139
01140 for(i=0; i< n; i++)
01141 {
01142 subs.watcher_user = ws_list[i].w_user;
01143 subs.watcher_domain = ws_list[i].w_domain;
01144 subs.status = ws_list[i].status;
01145 memset(&subs.reason, 0, sizeof(str));
01146
01147 if( pres_update_status(subs, reason, query_cols, query_vals,
01148 n_query_cols, &subs_array)< 0)
01149 {
01150 LM_ERR("failed to update watcher status\n");
01151 goto done;
01152 }
01153
01154 }
01155
01156 for(i=0; i< n; i++)
01157 {
01158 pkg_free(ws_list[i].w_user.s);
01159 pkg_free(ws_list[i].w_domain.s);
01160 if(ws_list[i].reason.s)
01161 pkg_free(ws_list[i].reason.s);
01162 }
01163 ws_list= NULL;
01164
01165 goto send_notify;
01166
01167 }
01168
01169 for(i = 0; i< result->n; i++)
01170 {
01171 row= &result->rows[i];
01172 row_vals = ROW_VALUES(row);
01173
01174 status= row_vals[status_col].val.int_val;
01175
01176 reason.s= (char*)row_vals[reason_col].val.string_val;
01177 reason.len= reason.s?strlen(reason.s):0;
01178
01179 w_user.s= (char*)row_vals[w_user_col].val.string_val;
01180 w_user.len= strlen(w_user.s);
01181
01182 w_domain.s= (char*)row_vals[w_domain_col].val.string_val;
01183 w_domain.len= strlen(w_domain.s);
01184
01185 subs.watcher_user= w_user;
01186 subs.watcher_domain= w_domain;
01187 subs.status= status;
01188 memset(&subs.reason, 0, sizeof(str));
01189
01190 if( pres_update_status(subs,reason, query_cols, query_vals,
01191 n_query_cols, &subs_array)< 0)
01192 {
01193 LM_ERR("failed to update watcher status\n");
01194 goto done;
01195 }
01196 }
01197
01198 pa_dbf.free_result(pa_db, result);
01199 result= NULL;
01200
01201 send_notify:
01202
01203 if (pres_notifier_processes == 0)
01204 {
01205 s= subs_array;
01206
01207 while(s)
01208 {
01209 if(notify(s, NULL, NULL, 0)< 0)
01210 {
01211 LM_ERR( "sending Notify request\n");
01212 goto done;
01213 }
01214
01215
01216 if(s->status== TERMINATED_STATUS)
01217 {
01218 if(pres_db_delete_status(s)<0)
01219 {
01220 LM_ERR("failed to delete terminated "
01221 "dialog from database\n");
01222 goto done;
01223 }
01224 }
01225
01226 s= s->next;
01227 }
01228 }
01229
01230 free_subs_list(subs_array, PKG_MEM_TYPE, 0);
01231 return 0;
01232
01233 done:
01234 if(result)
01235 pa_dbf.free_result(pa_db, result);
01236 free_subs_list(subs_array, PKG_MEM_TYPE, 0);
01237 if(ws_list)
01238 {
01239 for(i= 0; i< n; i++)
01240 {
01241 if(ws_list[i].w_user.s)
01242 pkg_free(ws_list[i].w_user.s);
01243 else
01244 break;
01245 if(ws_list[i].w_domain.s)
01246 pkg_free(ws_list[i].w_domain.s);
01247 if(ws_list[i].reason.s)
01248 pkg_free(ws_list[i].reason.s);
01249 }
01250 }
01251 return err_ret;
01252 }
01253
01254
01255
01256 static int update_pw_dialogs_dbonlymode(subs_t* subs, subs_t** subs_array)
01257 {
01258 db_key_t query_cols[5], db_cols[3];
01259 db_val_t query_vals[5], db_vals[3];
01260 db_key_t result_cols[24];
01261 int n_query_cols=0, n_result_cols=0, n_update_cols=0;
01262 int event_col, pres_uri_col, watcher_user_col, watcher_domain_col;
01263 int r_pres_uri_col,r_to_user_col,r_to_domain_col;
01264 int r_from_user_col,r_from_domain_col,r_callid_col;
01265 int r_to_tag_col,r_from_tag_col,r_sockinfo_col;
01266 int r_event_id_col,r_local_contact_col,r_contact_col;
01267 int r_record_route_col, r_reason_col;
01268 int r_event_col, r_local_cseq_col, r_remote_cseq_col;
01269 int r_status_col, r_version_col;
01270 int r_expires_col, r_watcher_user_col, r_watcher_domain_col;
01271 db1_res_t *result= NULL;
01272 db_val_t *row_vals;
01273 db_row_t *rows;
01274 int nr_rows, loop;
01275 subs_t s, *cs;
01276 str ev_sname;
01277
01278 if(pa_db == NULL)
01279 {
01280 LM_ERR("null database connection\n");
01281 return(-1);
01282 }
01283
01284 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
01285 {
01286 LM_ERR("use table failed\n");
01287 return(-1);
01288 }
01289
01290 query_cols[event_col=n_query_cols]= &str_event_col;
01291 query_vals[event_col].nul= 0;
01292 query_vals[event_col].type= DB1_STR;
01293 query_vals[event_col].val.str_val= subs->event->name ;
01294 n_query_cols++;
01295
01296 query_cols[pres_uri_col=n_query_cols]= &str_presentity_uri_col;
01297 query_vals[pres_uri_col].nul= 0;
01298 query_vals[pres_uri_col].type= DB1_STR;
01299 query_vals[pres_uri_col].val.str_val= subs->pres_uri;
01300 n_query_cols++;
01301
01302 query_cols[watcher_user_col=n_query_cols]= &str_watcher_username_col;
01303 query_vals[watcher_user_col].nul= 0;
01304 query_vals[watcher_user_col].type= DB1_STR;
01305 query_vals[watcher_user_col].val.str_val= subs->watcher_user;
01306 n_query_cols++;
01307
01308 query_cols[watcher_domain_col=n_query_cols]= &str_watcher_domain_col;
01309 query_vals[watcher_domain_col].nul= 0;
01310 query_vals[watcher_domain_col].type= DB1_STR;
01311 query_vals[watcher_domain_col].val.str_val= subs->watcher_domain;
01312 n_query_cols++;
01313
01314
01315 result_cols[r_to_user_col=n_result_cols++] = &str_to_user_col;
01316 result_cols[r_to_domain_col=n_result_cols++] = &str_to_domain_col;
01317 result_cols[r_from_user_col=n_result_cols++] = &str_from_user_col;
01318 result_cols[r_from_domain_col=n_result_cols++] = &str_from_domain_col;
01319 result_cols[r_watcher_user_col=n_result_cols++] = &str_watcher_username_col;
01320 result_cols[r_watcher_domain_col=n_result_cols++] = &str_watcher_domain_col;
01321 result_cols[r_callid_col=n_result_cols++] = &str_callid_col;
01322 result_cols[r_to_tag_col=n_result_cols++] = &str_to_tag_col;
01323 result_cols[r_from_tag_col=n_result_cols++] = &str_from_tag_col;
01324 result_cols[r_sockinfo_col=n_result_cols++] = &str_socket_info_col;
01325 result_cols[r_event_id_col=n_result_cols++] = &str_event_id_col;
01326 result_cols[r_local_contact_col=n_result_cols++] = &str_local_contact_col;
01327 result_cols[r_record_route_col=n_result_cols++] = &str_record_route_col;
01328 result_cols[r_reason_col=n_result_cols++] = &str_reason_col;
01329 result_cols[r_local_cseq_col=n_result_cols++] = &str_local_cseq_col;
01330 result_cols[r_version_col=n_result_cols++] = &str_version_col;
01331 result_cols[r_expires_col=n_result_cols++] = &str_expires_col;
01332 result_cols[r_event_col=n_result_cols++] = &str_event_col;
01333 result_cols[r_pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
01334 result_cols[r_contact_col=n_result_cols++] = &str_contact_col;
01335
01336
01337 result_cols[r_remote_cseq_col=n_result_cols++] = &str_remote_cseq_col;
01338 result_cols[r_status_col=n_result_cols++] = &str_status_col;
01339
01340
01341 if(pa_dbf.query(pa_db, query_cols, 0, query_vals, result_cols,
01342 n_query_cols, n_result_cols, 0, &result )< 0)
01343 {
01344 LM_ERR("Can't query db\n");
01345 if(result) pa_dbf.free_result(pa_db, result);
01346 return(-1);
01347 }
01348
01349 if(result == NULL) return(-1);
01350
01351 nr_rows = RES_ROW_N(result);
01352
01353 LM_DBG("found %d matching dialogs\n", nr_rows);
01354
01355
01356 for (loop=0; loop <nr_rows; loop++)
01357 {
01358 rows = RES_ROWS(result);
01359 row_vals = ROW_VALUES(rows);
01360
01361 memset(&s, 0, sizeof(subs_t));
01362 s.status= subs->status;
01363
01364 s.reason.s= subs->reason.s;
01365 s.reason.len= s.reason.s?strlen(s.reason.s):0;
01366
01367 s.pres_uri.s= (char*)row_vals[r_pres_uri_col].val.string_val;
01368 s.pres_uri.len= s.pres_uri.s?strlen(s.pres_uri.s):0;
01369
01370 s.to_user.s= (char*)row_vals[r_to_user_col].val.string_val;
01371 s.to_user.len= s.to_user.s?strlen(s.to_user.s):0;
01372
01373 s.to_domain.s= (char*)row_vals[r_to_domain_col].val.string_val;
01374 s.to_domain.len= s.to_domain.s?strlen(s.to_domain.s):0;
01375
01376 s.from_user.s= (char*)row_vals[r_from_user_col].val.string_val;
01377 s.from_user.len= s.from_user.s?strlen(s.from_user.s):0;
01378
01379 s.from_domain.s= (char*)row_vals[r_from_domain_col].val.string_val;
01380 s.from_domain.len= s.from_domain.s?strlen(s.from_domain.s):0;
01381
01382 s.watcher_user.s= (char*)row_vals[r_watcher_user_col].val.string_val;
01383 s.watcher_user.len= s.watcher_user.s?strlen(s.watcher_user.s):0;
01384
01385 s.watcher_domain.s= (char*)row_vals[r_watcher_domain_col].val.string_val;
01386 s.watcher_domain.len= s.watcher_domain.s?strlen(s.watcher_domain.s):0;
01387
01388 s.event_id.s=(char*)row_vals[r_event_id_col].val.string_val;
01389 s.event_id.len= (s.event_id.s)?strlen(s.event_id.s):0;
01390
01391 s.to_tag.s= (char*)row_vals[r_to_tag_col].val.string_val;
01392 s.to_tag.len= s.to_tag.s?strlen(s.to_tag.s):0;
01393
01394 s.from_tag.s= (char*)row_vals[r_from_tag_col].val.string_val;
01395 s.from_tag.len= s.from_tag.s?strlen(s.from_tag.s):0;
01396
01397 s.callid.s= (char*)row_vals[r_callid_col].val.string_val;
01398 s.callid.len= s.callid.s?strlen(s.callid.s):0;
01399
01400 s.record_route.s= (char*)row_vals[r_record_route_col].val.string_val;
01401 s.record_route.len= (s.record_route.s)?strlen(s.record_route.s):0;
01402
01403 s.contact.s= (char*)row_vals[r_contact_col].val.string_val;
01404 s.contact.len= s.contact.s?strlen(s.contact.s):0;
01405
01406 s.sockinfo_str.s = (char*)row_vals[r_sockinfo_col].val.string_val;
01407 s.sockinfo_str.len = s.sockinfo_str.s?strlen(s.sockinfo_str.s):0;
01408
01409 s.local_contact.s = (char*)row_vals[r_local_contact_col].val.string_val;
01410 s.local_contact.len = s.local_contact.s?strlen(s.local_contact.s):0;
01411
01412 ev_sname.s= (char*)row_vals[r_event_col].val.string_val;
01413 ev_sname.len= ev_sname.s?strlen(ev_sname.s):0;
01414
01415 s.event = contains_event(&ev_sname, NULL);
01416
01417 if(s.event == NULL)
01418 {
01419 LM_ERR("event not found and set to NULL\n");
01420 }
01421
01422 s.local_cseq = row_vals[r_local_cseq_col].val.int_val;
01423
01424 s.expires = row_vals[r_expires_col].val.int_val;
01425
01426 if( s.expires < (int)time(NULL) )
01427 s.expires = 0;
01428 else
01429 s.expires -= (int)time(NULL);
01430
01431 s.version = row_vals[r_version_col].val.int_val;
01432
01433 cs = mem_copy_subs(&s, PKG_MEM_TYPE);
01434 if (cs == NULL)
01435 {
01436 LM_ERR("while copying subs_t structure\n");
01437
01438 pa_dbf.free_result(pa_db, result);
01439 return(-1);
01440 }
01441 cs->local_cseq++;
01442 cs->next= (*subs_array);
01443 (*subs_array)= cs;
01444
01445 printf_subs(cs);
01446 }
01447
01448 pa_dbf.free_result(pa_db, result);
01449
01450 if (pres_notifier_processes == 0 && subs->status == TERMINATED_STATUS)
01451 {
01452
01453 if(pa_dbf.delete(pa_db, query_cols, 0, query_vals, n_query_cols)< 0)
01454 {
01455 LM_ERR("sql delete failed\n");
01456 return(-1);
01457 }
01458
01459 return(0);
01460 }
01461
01462
01463 db_cols[n_update_cols] = &str_status_col;
01464 db_vals[n_update_cols].type = DB1_INT;
01465 db_vals[n_update_cols].nul = 0;
01466 db_vals[n_update_cols].val.int_val = subs->status;
01467 n_update_cols++;
01468
01469 db_cols[n_update_cols] = &str_reason_col;
01470 db_vals[n_update_cols].type = DB1_STR;
01471 db_vals[n_update_cols].nul = 0;
01472 db_vals[n_update_cols].val.str_val= subs->reason;
01473 n_update_cols++;
01474
01475 db_cols[n_update_cols] = &str_updated_col;
01476 db_vals[n_update_cols].type = DB1_INT;
01477 db_vals[n_update_cols].nul = 0;
01478 db_vals[n_update_cols].val.int_val =
01479 core_hash(&subs->callid, &subs->from_tag,
01480 (pres_waitn_time * pres_notifier_poll_rate
01481 * pres_notifier_processes) - 1);
01482 n_update_cols++;
01483
01484
01485 if(pa_dbf.update(pa_db, query_cols, 0, query_vals,
01486 db_cols,db_vals,n_query_cols,n_update_cols) < 0)
01487 {
01488 LM_ERR("DB update failed\n");
01489 return(-1);
01490 }
01491
01492 return(0);
01493 }
01494
01495
01496
01497 static int update_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs_array)
01498 {
01499 subs_t* s, *ps, *cs;
01500 int i= 0;
01501
01502 LM_DBG("start\n");
01503
01504 if (subs_dbmode == DB_ONLY) return(update_pw_dialogs_dbonlymode(subs, subs_array));
01505
01506 lock_get(&subs_htable[hash_code].lock);
01507
01508 ps= subs_htable[hash_code].entries;
01509
01510 while(ps && ps->next)
01511 {
01512 s= ps->next;
01513
01514 if(s->event== subs->event && s->pres_uri.len== subs->pres_uri.len &&
01515 s->watcher_user.len== subs->watcher_user.len &&
01516 s->watcher_domain.len==subs->watcher_domain.len &&
01517 strncmp(s->pres_uri.s, subs->pres_uri.s, subs->pres_uri.len)== 0 &&
01518 strncmp(s->watcher_user.s, subs->watcher_user.s, s->watcher_user.len)== 0 &&
01519 strncmp(s->watcher_domain.s,subs->watcher_domain.s,s->watcher_domain.len)==0)
01520 {
01521 i++;
01522 s->status= subs->status;
01523 s->reason= subs->reason;
01524 s->db_flag= UPDATEDB_FLAG;
01525
01526 cs= mem_copy_subs(s, PKG_MEM_TYPE);
01527 if(cs== NULL)
01528 {
01529 LM_ERR( "copying subs_t stucture\n");
01530 lock_release(&subs_htable[hash_code].lock);
01531 return -1;
01532 }
01533 cs->local_cseq++;
01534 cs->expires-= (int)time(NULL);
01535 cs->next= (*subs_array);
01536 (*subs_array)= cs;
01537 if(subs->status== TERMINATED_STATUS)
01538 {
01539 ps->next= s->next;
01540 shm_free(s->contact.s);
01541 shm_free(s);
01542 LM_DBG(" deleted terminated dialog from hash table\n");
01543 }
01544 else
01545 ps= s;
01546
01547 printf_subs(cs);
01548 }
01549 else
01550 ps= s;
01551 }
01552
01553 LM_DBG("found %d matching dialogs\n", i);
01554 lock_release(&subs_htable[hash_code].lock);
01555
01556 return 0;
01557 }
01558
01559 static int w_pres_auth_status(struct sip_msg* _msg, char* _sp1, char* _sp2)
01560 {
01561 pv_spec_t *sp;
01562 pv_value_t pv_val;
01563 str watcher_uri, presentity_uri;
01564
01565 sp = (pv_spec_t *)_sp1;
01566
01567 if (sp && (pv_get_spec_value(_msg, sp, &pv_val) == 0)) {
01568 if (pv_val.flags & PV_VAL_STR) {
01569 watcher_uri = pv_val.rs;
01570 if (watcher_uri.len == 0 || watcher_uri.s == NULL) {
01571 LM_ERR("missing watcher uri\n");
01572 return -1;
01573 }
01574 } else {
01575 LM_ERR("watcher pseudo variable value is not string\n");
01576 return -1;
01577 }
01578 } else {
01579 LM_ERR("cannot get watcher pseudo variable value\n");
01580 return -1;
01581 }
01582
01583 sp = (pv_spec_t *)_sp2;
01584
01585 if (sp && (pv_get_spec_value(_msg, sp, &pv_val) == 0)) {
01586 if (pv_val.flags & PV_VAL_STR) {
01587 presentity_uri = pv_val.rs;
01588 if (presentity_uri.len == 0 || presentity_uri.s == NULL) {
01589 LM_DBG("missing presentity uri\n");
01590 return -1;
01591 }
01592 } else {
01593 LM_ERR("presentity pseudo variable value is not string\n");
01594 return -1;
01595 }
01596 } else {
01597 LM_ERR("cannot get presentity pseudo variable value\n");
01598 return -1;
01599 }
01600
01601 return pres_auth_status(_msg, watcher_uri, presentity_uri);
01602 }
01603
01604
01605 int pres_auth_status(struct sip_msg* msg, str watcher_uri, str presentity_uri)
01606 {
01607 str event;
01608 struct sip_uri uri;
01609 pres_ev_t* ev;
01610 str* rules_doc = NULL;
01611 subs_t subs;
01612 int res;
01613
01614 event.s = "presence";
01615 event.len = 8;
01616
01617 ev = contains_event(&event, NULL);
01618 if (ev == NULL) {
01619 LM_ERR("event is not registered\n");
01620 return -1;
01621 }
01622 if (ev->get_rules_doc == NULL) {
01623 LM_DBG("event does not require authorization");
01624 return ACTIVE_STATUS;
01625 }
01626 if (parse_uri(presentity_uri.s, presentity_uri.len, &uri) < 0) {
01627 LM_ERR("failed to parse presentity uri\n");
01628 return -1;
01629 }
01630 res = ev->get_rules_doc(&uri.user, &uri.host, &rules_doc);
01631 if ((res < 0) || (rules_doc == NULL) || (rules_doc->s == NULL)) {
01632 LM_DBG( "no xcap rules doc found for presentity uri\n");
01633 return PENDING_STATUS;
01634 }
01635
01636 if (parse_uri(watcher_uri.s, watcher_uri.len, &uri) < 0) {
01637 LM_ERR("failed to parse watcher uri\n");
01638 goto err;
01639 }
01640
01641 subs.watcher_user = uri.user;
01642 subs.watcher_domain = uri.host;
01643 subs.pres_uri = presentity_uri;
01644 subs.auth_rules_doc = rules_doc;
01645 if (ev->get_auth_status(&subs) < 0) {
01646 LM_ERR( "getting status from rules document\n");
01647 goto err;
01648 }
01649 LM_DBG("auth status of watcher <%.*s> on presentity <%.*s> is %d\n",
01650 watcher_uri.len, watcher_uri.s, presentity_uri.len, presentity_uri.s,
01651 subs.status);
01652 pkg_free(rules_doc->s);
01653 pkg_free(rules_doc);
01654 if ((subs.reason.len == 12) && (strncmp(subs.reason.s, "polite-block", 12) == 0))
01655 return POLITE_BLOCK_STATUS;
01656 return subs.status;
01657
01658 err:
01659 pkg_free(rules_doc->s);
01660 pkg_free(rules_doc);
01661 return -1;
01662 }
01663
01667 static int w_pres_refresh_watchers(struct sip_msg *msg, char *puri,
01668 char *pevent, char *ptype)
01669 {
01670 str pres_uri;
01671 str event;
01672 int refresh_type;
01673
01674 if(fixup_get_svalue(msg, (gparam_p)puri, &pres_uri)!=0)
01675 {
01676 LM_ERR("invalid uri parameter");
01677 return -1;
01678 }
01679
01680 if(fixup_get_svalue(msg, (gparam_p)pevent, &event)!=0)
01681 {
01682 LM_ERR("invalid uri parameter");
01683 return -1;
01684 }
01685
01686 if(fixup_get_ivalue(msg, (gparam_p)ptype, &refresh_type)!=0)
01687 {
01688 LM_ERR("no type value\n");
01689 return -1;
01690 }
01691
01692 if(pres_refresh_watchers(&pres_uri, &event, refresh_type)<0)
01693 return -1;
01694
01695 return 1;
01696 }
01697
01701 static int fixup_refresh_watchers(void** param, int param_no)
01702 {
01703 if(param_no==1)
01704 {
01705 return fixup_spve_null(param, 1);
01706 } else if(param_no==2) {
01707 return fixup_spve_null(param, 1);
01708 } else if(param_no==3) {
01709 return fixup_igp_null(param, 1);
01710 }
01711 return 0;
01712 }
01713
01714
01718 static int w_pres_update_watchers(struct sip_msg *msg, char *puri,
01719 char *pevent)
01720 {
01721 str pres_uri;
01722 str event;
01723 pres_ev_t* ev;
01724 struct sip_uri uri;
01725 str* rules_doc = NULL;
01726 int ret;
01727
01728 if(fixup_get_svalue(msg, (gparam_p)puri, &pres_uri)!=0)
01729 {
01730 LM_ERR("invalid uri parameter");
01731 return -1;
01732 }
01733
01734 if(fixup_get_svalue(msg, (gparam_p)pevent, &event)!=0)
01735 {
01736 LM_ERR("invalid uri parameter");
01737 return -1;
01738 }
01739
01740 ev = contains_event(&event, NULL);
01741 if(ev==NULL)
01742 {
01743 LM_ERR("event %.*s is not registered\n",
01744 event.len, event.s);
01745 return -1;
01746 }
01747 if(ev->get_rules_doc==NULL)
01748 {
01749 LM_DBG("event %.*s does not provide rules doc API\n",
01750 event.len, event.s);
01751 return -1;
01752 }
01753 if(parse_uri(pres_uri.s, pres_uri.len, &uri)<0)
01754 {
01755 LM_ERR("failed to parse presentity uri [%.*s]\n",
01756 pres_uri.len, pres_uri.s);
01757 return -1;
01758 }
01759 ret = ev->get_rules_doc(&uri.user, &uri.host, &rules_doc);
01760 if((ret < 0) || (rules_doc==NULL) || (rules_doc->s==NULL))
01761 {
01762 LM_DBG("no xcap rules doc found for presentity uri [%.*s]\n",
01763 pres_uri.len, pres_uri.s);
01764 if(rules_doc != NULL)
01765 pkg_free(rules_doc);
01766 return -1;
01767 }
01768 ret = 1;
01769 if(update_watchers_status(pres_uri, ev, rules_doc)<0)
01770 {
01771 LM_ERR("updating watchers in presence\n");
01772 ret = -1;
01773 }
01774
01775 pkg_free(rules_doc->s);
01776 pkg_free(rules_doc);
01777
01778 return ret;
01779 }
01780
01784 static int fixup_update_watchers(void** param, int param_no)
01785 {
01786 if(param_no==1)
01787 {
01788 return fixup_spve_null(param, 1);
01789 } else if(param_no==2) {
01790 return fixup_spve_null(param, 1);
01791 }
01792 return 0;
01793 }
01794
01798 static int fixup_update_presentity(void** param, int param_no)
01799 {
01800 if(param_no==1 || param_no==2 || param_no==3)
01801 return fixup_spve_null(param, 1);
01802
01803 return 0;
01804 }