00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include <stdio.h>
00046 #include <string.h>
00047 #include <stdlib.h>
00048 #include <sys/types.h>
00049 #include <sys/ipc.h>
00050 #include <unistd.h>
00051 #include <fcntl.h>
00052 #include <time.h>
00053
00054 #include "../../db/db.h"
00055 #include "../../sr_module.h"
00056 #include "../../dprint.h"
00057 #include "../../error.h"
00058 #include "../../ut.h"
00059 #include "../../parser/parse_to.h"
00060 #include "../../parser/parse_uri.h"
00061 #include "../../parser/parse_content.h"
00062 #include "../../parser/parse_from.h"
00063 #include "../../mem/mem.h"
00064 #include "../../mem/shm_mem.h"
00065 #include "../../usr_avp.h"
00066 #include "../tm/tm_load.h"
00067 #include "../sl/sl_api.h"
00068 #include "../../pt.h"
00069 #include "../../mi/mi.h"
00070 #include "../pua/hash.h"
00071 #include "publish.h"
00072 #include "subscribe.h"
00073 #include "event_list.h"
00074 #include "bind_presence.h"
00075 #include "notify.h"
00076
00077 MODULE_VERSION
00078
00079 #define S_TABLE_VERSION 3
00080 #define P_TABLE_VERSION 3
00081 #define ACTWATCH_TABLE_VERSION 9
00082
00083 char *log_buf = NULL;
00084 static int clean_period=100;
00085 static int db_update_period=100;
00086
00087
00088 db_con_t *pa_db = NULL;
00089 db_func_t pa_dbf;
00090 str presentity_table= str_init("presentity");
00091 str active_watchers_table = str_init("active_watchers");
00092 str watchers_table= str_init("watchers");
00093
00094 int library_mode= 0;
00095 str server_address= {0, 0};
00096 evlist_t* EvList= NULL;
00097
00098
00099 char* to_tag_pref = "10";
00100
00101
00102 struct tm_binds tmb;
00103
00104 struct sl_binds slb;
00105
00106
00107
00108 static int mod_init(void);
00109 static int child_init(int);
00110 static void destroy(void);
00111 int stored_pres_info(struct sip_msg* msg, char* pres_uri, char* s);
00112 static int fixup_presence(void** param, int param_no);
00113 static int fixup_subscribe(void** param, int param_no);
00114 static struct mi_root* mi_refreshWatchers(struct mi_root* cmd, void* param);
00115 static struct mi_root* mi_cleanup(struct mi_root* cmd, void* param);
00116 static int update_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs_array);
00117 int update_watchers_status(str pres_uri, pres_ev_t* ev, str* rules_doc);
00118 static int mi_child_init(void);
00119
00120 int counter =0;
00121 int pid = 0;
00122 char prefix='a';
00123 int startup_time=0;
00124 str db_url = {0, 0};
00125 int expires_offset = 0;
00126 int max_expires= 3600;
00127 int shtable_size= 9;
00128 shtable_t subs_htable= NULL;
00129 int fallback2db= 0;
00130 int sphere_enable= 0;
00131
00132 int phtable_size= 9;
00133 phtable_t* pres_htable;
00134
00135 static cmd_export_t cmds[]=
00136 {
00137 {"handle_publish", (cmd_function)handle_publish, 0,fixup_presence,0, REQUEST_ROUTE},
00138 {"handle_publish", (cmd_function)handle_publish, 1,fixup_presence, 0, REQUEST_ROUTE},
00139 {"handle_subscribe",(cmd_function)handle_subscribe,0,fixup_subscribe,0, REQUEST_ROUTE},
00140 {"bind_presence", (cmd_function)bind_presence, 1, 0, 0, 0},
00141 { 0, 0, 0, 0, 0, 0}
00142 };
00143
00144 static param_export_t params[]={
00145 { "db_url", STR_PARAM, &db_url.s},
00146 { "presentity_table", STR_PARAM, &presentity_table.s},
00147 { "active_watchers_table", STR_PARAM, &active_watchers_table.s},
00148 { "watchers_table", STR_PARAM, &watchers_table.s},
00149 { "clean_period", INT_PARAM, &clean_period },
00150 { "db_update_period", INT_PARAM, &db_update_period },
00151 { "to_tag_pref", STR_PARAM, &to_tag_pref },
00152 { "expires_offset", INT_PARAM, &expires_offset },
00153 { "max_expires", INT_PARAM, &max_expires },
00154 { "server_address", STR_PARAM, &server_address.s},
00155 { "subs_htable_size", INT_PARAM, &shtable_size},
00156 { "pres_htable_size", INT_PARAM, &phtable_size},
00157 { "fallback2db", INT_PARAM, &fallback2db},
00158 { "enable_sphere_check", INT_PARAM, &sphere_enable},
00159 {0,0,0}
00160 };
00161
00162 static mi_export_t mi_cmds[] = {
00163 { "refreshWatchers", mi_refreshWatchers, 0, 0, mi_child_init},
00164 { "cleanup", mi_cleanup, 0, 0, mi_child_init},
00165 { 0, 0, 0, 0, 0}
00166 };
00167
00168
00169 struct module_exports exports= {
00170 "presence",
00171 DEFAULT_DLFLAGS,
00172 cmds,
00173 params,
00174 0,
00175 mi_cmds,
00176 0,
00177 0,
00178 mod_init,
00179 0,
00180 (destroy_function) destroy,
00181 child_init
00182 };
00183
00184
00185
00186
00187 static int mod_init(void)
00188 {
00189 db_url.len = db_url.s ? strlen(db_url.s) : 0;
00190 LM_DBG("db_url=%s/%d/%p\n", ZSW(db_url.s), db_url.len,db_url.s);
00191 presentity_table.len = strlen(presentity_table.s);
00192 active_watchers_table.len = strlen(active_watchers_table.s);
00193 watchers_table.len = strlen(watchers_table.s);
00194
00195 if(db_url.s== NULL)
00196 library_mode= 1;
00197
00198 if(library_mode== 1)
00199 {
00200 LM_DBG("Presence module used for API library purpose only\n");
00201 EvList= init_evlist();
00202 if(!EvList)
00203 {
00204 LM_ERR("unsuccessful initialize event list\n");
00205 return -1;
00206 }
00207 return 0;
00208 }
00209
00210 if(expires_offset<0)
00211 expires_offset = 0;
00212
00213 if(to_tag_pref==NULL || strlen(to_tag_pref)==0)
00214 to_tag_pref="10";
00215
00216 if(max_expires<= 0)
00217 max_expires = 3600;
00218
00219 if(server_address.s== NULL)
00220 LM_DBG("server_address parameter not set in configuration file\n");
00221
00222 if(server_address.s)
00223 server_address.len= strlen(server_address.s);
00224 else
00225 server_address.len= 0;
00226
00227
00228 if(load_sl_api(&slb)==-1)
00229 {
00230 LM_ERR("Can't load sl functions. Module SL not loaded?\n");
00231 return -1;
00232 }
00233
00234
00235 if(load_tm_api(&tmb)==-1)
00236 {
00237 LM_ERR("Can't load tm functions. Module TM not loaded?\n");
00238 return -1;
00239 }
00240
00241 if(db_url.s== NULL)
00242 {
00243 LM_ERR("database url not set!\n");
00244 return -1;
00245 }
00246
00247
00248 if (db_bind_mod(&db_url, &pa_dbf))
00249 {
00250 LM_ERR("Database module not found\n");
00251 return -1;
00252 }
00253
00254
00255 if (!DB_CAPABILITY(pa_dbf, DB_CAP_ALL))
00256 {
00257 LM_ERR("Database module does not implement all functions"
00258 " needed by presence module\n");
00259 return -1;
00260 }
00261
00262 pa_db = pa_dbf.init(&db_url);
00263 if (!pa_db)
00264 {
00265 LM_ERR("Connection to database failed\n");
00266 return -1;
00267 }
00268
00269
00270 if((db_check_table_version(&pa_dbf, pa_db, &presentity_table, P_TABLE_VERSION) < 0) ||
00271 (db_check_table_version(&pa_dbf, pa_db, &active_watchers_table, ACTWATCH_TABLE_VERSION) < 0) ||
00272 (db_check_table_version(&pa_dbf, pa_db, &watchers_table, S_TABLE_VERSION) < 0)) {
00273 LM_ERR("error during table version check\n");
00274 return -1;
00275 }
00276
00277 EvList= init_evlist();
00278 if(!EvList)
00279 {
00280 LM_ERR("initializing event list\n");
00281 return -1;
00282 }
00283
00284 if(shtable_size< 1)
00285 shtable_size= 512;
00286 else
00287 shtable_size= 1<< shtable_size;
00288
00289 subs_htable= new_shtable(shtable_size);
00290 if(subs_htable== NULL)
00291 {
00292 LM_ERR(" initializing subscribe hash table\n");
00293 return -1;
00294 }
00295
00296 if(restore_db_subs()< 0)
00297 {
00298 LM_ERR("restoring subscribe info from database\n");
00299 return -1;
00300 }
00301
00302 if(phtable_size< 1)
00303 phtable_size= 256;
00304 else
00305 phtable_size= 1<< phtable_size;
00306
00307 pres_htable= new_phtable();
00308 if(pres_htable== NULL)
00309 {
00310 LM_ERR("initializing presentity hash table\n");
00311 return -1;
00312 }
00313
00314 if(pres_htable_restore()< 0)
00315 {
00316 LM_ERR("filling in presentity hash table from database\n");
00317 return -1;
00318 }
00319
00320 startup_time = (int) time(NULL);
00321
00322 if(clean_period>0)
00323 {
00324 register_timer(msg_presentity_clean, 0, clean_period);
00325 register_timer(msg_watchers_clean, 0, clean_period);
00326 }
00327
00328 if(db_update_period>0)
00329 register_timer(timer_db_update, 0, db_update_period);
00330
00331 if(pa_db)
00332 pa_dbf.close(pa_db);
00333 pa_db = NULL;
00334
00335 return 0;
00336 }
00337
00338
00339
00340
00341 static int child_init(int rank)
00342 {
00343 pid = my_pid();
00344
00345 if(library_mode)
00346 return 0;
00347
00348 if (pa_dbf.init==0)
00349 {
00350 LM_CRIT("child_init: database not bound\n");
00351 return -1;
00352 }
00353 pa_db = pa_dbf.init(&db_url);
00354 if (!pa_db)
00355 {
00356 LM_ERR("child %d: unsuccessful connecting to database\n", rank);
00357 return -1;
00358 }
00359
00360 if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
00361 {
00362 LM_ERR( "child %d:unsuccessful use_table presentity_table\n", rank);
00363 return -1;
00364 }
00365
00366 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
00367 {
00368 LM_ERR( "child %d:unsuccessful use_table active_watchers_table\n",
00369 rank);
00370 return -1;
00371 }
00372
00373 if (pa_dbf.use_table(pa_db, &watchers_table) < 0)
00374 {
00375 LM_ERR( "child %d:unsuccessful use_table watchers_table\n", rank);
00376 return -1;
00377 }
00378
00379 LM_DBG("child %d: Database connection opened successfully\n", rank);
00380
00381 return 0;
00382 }
00383
00384 static int mi_child_init(void)
00385 {
00386 if(library_mode)
00387 return 0;
00388
00389 if (pa_dbf.init==0)
00390 {
00391 LM_CRIT("database not bound\n");
00392 return -1;
00393 }
00394 pa_db = pa_dbf.init(&db_url);
00395 if (!pa_db)
00396 {
00397 LM_ERR("connecting database\n");
00398 return -1;
00399 }
00400
00401 if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
00402 {
00403 LM_ERR( "unsuccessful use_table presentity_table\n");
00404 return -1;
00405 }
00406
00407 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
00408 {
00409 LM_ERR( "unsuccessful use_table active_watchers_table\n");
00410 return -1;
00411 }
00412
00413 if (pa_dbf.use_table(pa_db, &watchers_table) < 0)
00414 {
00415 LM_ERR( "unsuccessful use_table watchers_table\n");
00416 return -1;
00417 }
00418
00419 LM_DBG("Database connection opened successfully\n");
00420 return 0;
00421 }
00422
00423
00424
00425
00426
00427 static void destroy(void)
00428 {
00429 if(subs_htable && pa_db)
00430 timer_db_update(0, 0);
00431
00432 if(subs_htable)
00433 destroy_shtable(subs_htable, shtable_size);
00434
00435 if(pres_htable)
00436 destroy_phtable();
00437
00438 if(pa_db && pa_dbf.close)
00439 pa_dbf.close(pa_db);
00440
00441 destroy_evlist();
00442 }
00443
00444 static int fixup_presence(void** param, int param_no)
00445 {
00446 pv_elem_t *model;
00447 str s;
00448
00449 if(library_mode)
00450 {
00451 LM_ERR("Bad config - you can not call 'handle_publish' function"
00452 " (db_url not set)\n");
00453 return -1;
00454 }
00455 if(param_no== 0)
00456 return 0;
00457
00458 if(*param)
00459 {
00460 s.s = (char*)(*param); s.len = strlen(s.s);
00461 if(pv_parse_format(&s, &model)<0)
00462 {
00463 LM_ERR( "wrong format[%s]\n",(char*)(*param));
00464 return E_UNSPEC;
00465 }
00466
00467 *param = (void*)model;
00468 return 0;
00469 }
00470 LM_ERR( "null format\n");
00471 return E_UNSPEC;
00472 }
00473
00474 static int fixup_subscribe(void** param, int param_no)
00475 {
00476
00477 if(library_mode)
00478 {
00479 LM_ERR("Bad config - you can not call 'handle_subscribe' function"
00480 " (db_url not set)\n");
00481 return -1;
00482 }
00483 return 0;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 static struct mi_root* mi_refreshWatchers(struct mi_root* cmd, void* param)
00495 {
00496 struct mi_node* node= NULL;
00497 str pres_uri, event;
00498 struct sip_uri uri;
00499 pres_ev_t* ev;
00500 str* rules_doc= NULL;
00501 int result;
00502 unsigned int refresh_type;
00503
00504 LM_DBG("start\n");
00505
00506 node = cmd->node.kids;
00507 if(node == NULL)
00508 return 0;
00509
00510
00511 pres_uri = node->value;
00512 if(pres_uri.s == NULL || pres_uri.len== 0)
00513 {
00514 LM_ERR( "empty uri\n");
00515 return init_mi_tree(404, "Empty presentity URI", 20);
00516 }
00517
00518 node = node->next;
00519 if(node == NULL)
00520 return 0;
00521 event= node->value;
00522 if(event.s== NULL || event.len== 0)
00523 {
00524 LM_ERR( "empty event parameter\n");
00525 return init_mi_tree(400, "Empty event parameter", 21);
00526 }
00527 LM_DBG("event '%.*s'\n", event.len, event.s);
00528
00529 node = node->next;
00530 if(node == NULL)
00531 return 0;
00532 if(node->value.s== NULL || node->value.len== 0)
00533 {
00534 LM_ERR( "empty event parameter\n");
00535 return init_mi_tree(400, "Empty event parameter", 21);
00536 }
00537 if(str2int(&node->value, &refresh_type)< 0)
00538 {
00539 LM_ERR("converting string to int\n");
00540 goto error;
00541 }
00542
00543 if(node->next!= NULL)
00544 {
00545 LM_ERR( "Too many parameters\n");
00546 return init_mi_tree(400, "Too many parameters", 19);
00547 }
00548
00549 ev= contains_event(&event, NULL);
00550 if(ev== NULL)
00551 {
00552 LM_ERR( "wrong event parameter\n");
00553 return 0;
00554 }
00555
00556 if(refresh_type== 0)
00557 {
00558 if(ev->get_rules_doc== NULL)
00559 {
00560 LM_ERR("wrong request for a refresh watchers authorization status"
00561 "for an event that does not require authorization\n");
00562 goto error;
00563 }
00564
00565 if(parse_uri(pres_uri.s, pres_uri.len, &uri)< 0)
00566 {
00567 LM_ERR( "parsing uri\n");
00568 goto error;
00569 }
00570
00571 result= ev->get_rules_doc(&uri.user,&uri.host,&rules_doc);
00572 if(result< 0 || rules_doc==NULL || rules_doc->s== NULL)
00573 {
00574 LM_ERR( "no rules doc found for the user\n");
00575 goto error;
00576 }
00577
00578 if(update_watchers_status(pres_uri, ev, rules_doc)< 0)
00579 {
00580 LM_ERR("failed to update watchers\n");
00581 goto error;
00582 }
00583
00584 pkg_free(rules_doc->s);
00585 pkg_free(rules_doc);
00586 rules_doc = NULL;
00587
00588 }
00589 else
00590 {
00591 if(query_db_notify(&pres_uri, ev, NULL)< 0)
00592 {
00593 LM_ERR("sending Notify requests\n");
00594 goto error;
00595 }
00596
00597 }
00598
00599 return init_mi_tree(200, "OK", 2);
00600
00601 error:
00602 if(rules_doc)
00603 {
00604 if(rules_doc->s)
00605 pkg_free(rules_doc->s);
00606 pkg_free(rules_doc);
00607 }
00608 return 0;
00609 }
00610
00611
00612
00613
00614
00615 static struct mi_root* mi_cleanup(struct mi_root* cmd, void* param)
00616 {
00617 LM_DBG("mi_cleanup:start\n");
00618
00619 (void)msg_watchers_clean(0,0);
00620 (void)msg_presentity_clean(0,0);
00621
00622 return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00623 }
00624
00625 int pres_update_status(subs_t subs, str reason, db_key_t* query_cols,
00626 db_val_t* query_vals, int n_query_cols, subs_t** subs_array)
00627 {
00628 db_key_t update_cols[5];
00629 db_val_t update_vals[5];
00630 int n_update_cols= 0;
00631 int u_status_col, u_reason_col, q_wuser_col, q_wdomain_col;
00632 int status;
00633 query_cols[q_wuser_col=n_query_cols]= &str_watcher_username_col;
00634 query_vals[n_query_cols].nul= 0;
00635 query_vals[n_query_cols].type= DB_STR;
00636 n_query_cols++;
00637
00638 query_cols[q_wdomain_col=n_query_cols]= &str_watcher_domain_col;
00639 query_vals[n_query_cols].nul= 0;
00640 query_vals[n_query_cols].type= DB_STR;
00641 n_query_cols++;
00642
00643 update_cols[u_status_col= n_update_cols]= &str_status_col;
00644 update_vals[u_status_col].nul= 0;
00645 update_vals[u_status_col].type= DB_INT;
00646 n_update_cols++;
00647
00648 update_cols[u_reason_col= n_update_cols]= &str_reason_col;
00649 update_vals[u_reason_col].nul= 0;
00650 update_vals[u_reason_col].type= DB_STR;
00651 n_update_cols++;
00652
00653 status= subs.status;
00654 if(subs.event->get_auth_status(&subs)< 0)
00655 {
00656 LM_ERR( "getting status from rules document\n");
00657 return -1;
00658 }
00659 LM_DBG("subs.status= %d\n", subs.status);
00660 if(get_status_str(subs.status)== NULL)
00661 {
00662 LM_ERR("wrong status: %d\n", subs.status);
00663 return -1;
00664 }
00665
00666 if(subs.status!= status || reason.len!= subs.reason.len ||
00667 (reason.s && subs.reason.s && strncmp(reason.s, subs.reason.s,
00668 reason.len)))
00669 {
00670
00671 query_vals[q_wuser_col].val.str_val= subs.from_user;
00672 query_vals[q_wdomain_col].val.str_val= subs.from_domain;
00673
00674 update_vals[u_status_col].val.int_val= subs.status;
00675 update_vals[u_reason_col].val.str_val= subs.reason;
00676
00677 if (pa_dbf.use_table(pa_db, &watchers_table) < 0)
00678 {
00679 LM_ERR( "in use_table\n");
00680 return -1;
00681 }
00682
00683 if(pa_dbf.update(pa_db, query_cols, 0, query_vals, update_cols,
00684 update_vals, n_query_cols, n_update_cols)< 0)
00685 {
00686 LM_ERR( "in sql update\n");
00687 return -1;
00688 }
00689
00690
00691 if(update_pw_dialogs(&subs, subs.db_flag, subs_array)< 0)
00692 {
00693 LM_ERR( "extracting dialogs from [watcher]=%.*s@%.*s to"
00694 " [presentity]=%.*s\n", subs.from_user.len, subs.from_user.s,
00695 subs.from_domain.len, subs.from_domain.s, subs.pres_uri.len,
00696 subs.pres_uri.s);
00697 return -1;
00698 }
00699 }
00700 return 0;
00701 }
00702
00703 int pres_db_delete_status(subs_t* s)
00704 {
00705 int n_query_cols= 0;
00706 db_key_t query_cols[5];
00707 db_val_t query_vals[5];
00708
00709 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
00710 {
00711 LM_ERR("sql use table failed\n");
00712 return -1;
00713 }
00714
00715 query_cols[n_query_cols]= &str_event_col;
00716 query_vals[n_query_cols].nul= 0;
00717 query_vals[n_query_cols].type= DB_STR;
00718 query_vals[n_query_cols].val.str_val= s->event->name ;
00719 n_query_cols++;
00720
00721 query_cols[n_query_cols]= &str_presentity_uri_col;
00722 query_vals[n_query_cols].nul= 0;
00723 query_vals[n_query_cols].type= DB_STR;
00724 query_vals[n_query_cols].val.str_val= s->pres_uri;
00725 n_query_cols++;
00726
00727 query_cols[n_query_cols]= &str_watcher_username_col;
00728 query_vals[n_query_cols].nul= 0;
00729 query_vals[n_query_cols].type= DB_STR;
00730 query_vals[n_query_cols].val.str_val= s->from_user;
00731 n_query_cols++;
00732
00733 query_cols[n_query_cols]= &str_watcher_domain_col;
00734 query_vals[n_query_cols].nul= 0;
00735 query_vals[n_query_cols].type= DB_STR;
00736 query_vals[n_query_cols].val.str_val= s->from_domain;
00737 n_query_cols++;
00738
00739 if(pa_dbf.delete(pa_db, query_cols, 0, query_vals, n_query_cols)< 0)
00740 {
00741 LM_ERR("sql delete failed\n");
00742 return -1;
00743 }
00744 return 0;
00745
00746 }
00747
00748 int update_watchers_status(str pres_uri, pres_ev_t* ev, str* rules_doc)
00749 {
00750 subs_t subs;
00751 db_key_t query_cols[6], result_cols[5];
00752 db_val_t query_vals[6];
00753 int n_result_cols= 0, n_query_cols = 0;
00754 db_res_t* result= NULL;
00755 db_row_t *row;
00756 db_val_t *row_vals ;
00757 int i;
00758 str w_user, w_domain, reason= {0, 0};
00759 unsigned int status;
00760 int status_col, w_user_col, w_domain_col, reason_col;
00761 subs_t* subs_array= NULL,* s;
00762 unsigned int hash_code;
00763 int err_ret= -1;
00764 int n= 0;
00765
00766 typedef struct ws
00767 {
00768 int status;
00769 str reason;
00770 str w_user;
00771 str w_domain;
00772 }ws_t;
00773 ws_t* ws_list= NULL;
00774
00775 LM_DBG("start\n");
00776
00777 if(ev->content_type.s== NULL)
00778 {
00779 ev= contains_event(&ev->name, NULL);
00780 if(ev== NULL)
00781 {
00782 LM_ERR("wrong event parameter\n");
00783 return 0;
00784 }
00785 }
00786
00787 subs.pres_uri= pres_uri;
00788 subs.event= ev;
00789 subs.auth_rules_doc= rules_doc;
00790
00791
00792 query_cols[n_query_cols]= &str_presentity_uri_col;
00793 query_vals[n_query_cols].nul= 0;
00794 query_vals[n_query_cols].type= DB_STR;
00795 query_vals[n_query_cols].val.str_val= pres_uri;
00796 n_query_cols++;
00797
00798 query_cols[n_query_cols]= &str_event_col;
00799 query_vals[n_query_cols].nul= 0;
00800 query_vals[n_query_cols].type= DB_STR;
00801 query_vals[n_query_cols].val.str_val= ev->name;
00802 n_query_cols++;
00803
00804 result_cols[status_col= n_result_cols++]= &str_status_col;
00805 result_cols[reason_col= n_result_cols++]= &str_reason_col;
00806 result_cols[w_user_col= n_result_cols++]= &str_watcher_username_col;
00807 result_cols[w_domain_col= n_result_cols++]= &str_watcher_domain_col;
00808
00809 if (pa_dbf.use_table(pa_db, &watchers_table) < 0)
00810 {
00811 LM_ERR( "in use_table\n");
00812 goto done;
00813 }
00814
00815 if(pa_dbf.query(pa_db, query_cols, 0, query_vals, result_cols,n_query_cols,
00816 n_result_cols, 0, &result)< 0)
00817 {
00818 LM_ERR( "in sql query\n");
00819 goto done;
00820 }
00821 if(result== NULL)
00822 return 0;
00823
00824 if(result->n<= 0)
00825 {
00826 err_ret= 0;
00827 goto done;
00828 }
00829
00830 LM_DBG("found %d record-uri in watchers_table\n", result->n);
00831 hash_code= core_hash(&pres_uri, &ev->name, shtable_size);
00832 subs.db_flag= hash_code;
00833
00834
00835 if(sphere_enable)
00836 {
00837 n= result->n;
00838 ws_list= (ws_t*)pkg_malloc(n * sizeof(ws_t));
00839 if(ws_list== NULL)
00840 {
00841 LM_ERR("No more private memory\n");
00842 goto done;
00843 }
00844 memset(ws_list, 0, n * sizeof(ws_t));
00845
00846 for(i= 0; i< result->n ; i++)
00847 {
00848 row= &result->rows[i];
00849 row_vals = ROW_VALUES(row);
00850
00851 status= row_vals[status_col].val.int_val;
00852
00853 reason.s= (char*)row_vals[reason_col].val.string_val;
00854 reason.len= reason.s?strlen(reason.s):0;
00855
00856 w_user.s= (char*)row_vals[w_user_col].val.string_val;
00857 w_user.len= strlen(w_user.s);
00858
00859 w_domain.s= (char*)row_vals[w_domain_col].val.string_val;
00860 w_domain.len= strlen(w_domain.s);
00861
00862 if(reason.len)
00863 {
00864 ws_list[i].reason.s = (char*)pkg_malloc(reason.len* sizeof(char));
00865 if(ws_list[i].reason.s== NULL)
00866 {
00867 LM_ERR("No more private memory\n");
00868 goto done;
00869 }
00870 memcpy(ws_list[i].reason.s, reason.s, reason.len);
00871 ws_list[i].reason.len= reason.len;
00872 }
00873 else
00874 ws_list[i].reason.s= NULL;
00875
00876 ws_list[i].w_user.s = (char*)pkg_malloc(w_user.len* sizeof(char));
00877 if(ws_list[i].w_user.s== NULL)
00878 {
00879 LM_ERR("No more private memory\n");
00880 goto done;
00881
00882 }
00883 memcpy(ws_list[i].w_user.s, w_user.s, w_user.len);
00884 ws_list[i].w_user.len= w_user.len;
00885
00886 ws_list[i].w_domain.s = (char*)pkg_malloc(w_domain.len* sizeof(char));
00887 if(ws_list[i].w_domain.s== NULL)
00888 {
00889 LM_ERR("No more private memory\n");
00890 goto done;
00891 }
00892 memcpy(ws_list[i].w_domain.s, w_domain.s, w_domain.len);
00893 ws_list[i].w_domain.len= w_domain.len;
00894
00895 ws_list[i].status= status;
00896 }
00897
00898 pa_dbf.free_result(pa_db, result);
00899 result= NULL;
00900
00901 for(i=0; i< n; i++)
00902 {
00903 subs.from_user = ws_list[i].w_user;
00904 subs.from_domain = ws_list[i].w_domain;
00905 subs.status = ws_list[i].status;
00906 memset(&subs.reason, 0, sizeof(str));
00907
00908 if( pres_update_status(subs, reason, query_cols, query_vals,
00909 n_query_cols, &subs_array)< 0)
00910 {
00911 LM_ERR("failed to update watcher status\n");
00912 goto done;
00913 }
00914
00915 }
00916
00917 for(i=0; i< n; i++)
00918 {
00919 pkg_free(ws_list[i].w_user.s);
00920 pkg_free(ws_list[i].w_domain.s);
00921 if(ws_list[i].reason.s)
00922 pkg_free(ws_list[i].reason.s);
00923 }
00924 ws_list= NULL;
00925
00926 goto send_notify;
00927
00928 }
00929
00930 for(i = 0; i< result->n; i++)
00931 {
00932 row= &result->rows[i];
00933 row_vals = ROW_VALUES(row);
00934
00935 status= row_vals[status_col].val.int_val;
00936
00937 reason.s= (char*)row_vals[reason_col].val.string_val;
00938 reason.len= reason.s?strlen(reason.s):0;
00939
00940 w_user.s= (char*)row_vals[w_user_col].val.string_val;
00941 w_user.len= strlen(w_user.s);
00942
00943 w_domain.s= (char*)row_vals[w_domain_col].val.string_val;
00944 w_domain.len= strlen(w_domain.s);
00945
00946 subs.from_user= w_user;
00947 subs.from_domain= w_domain;
00948 subs.status= status;
00949 memset(&subs.reason, 0, sizeof(str));
00950
00951 if( pres_update_status(subs,reason, query_cols, query_vals,
00952 n_query_cols, &subs_array)< 0)
00953 {
00954 LM_ERR("failed to update watcher status\n");
00955 goto done;
00956 }
00957 }
00958
00959 pa_dbf.free_result(pa_db, result);
00960 result= NULL;
00961
00962 send_notify:
00963
00964 s= subs_array;
00965
00966 while(s)
00967 {
00968
00969 if(notify(s, NULL, NULL, 0)< 0)
00970 {
00971 LM_ERR( "sending Notify request\n");
00972 goto done;
00973 }
00974
00975
00976 if(s->status== TERMINATED_STATUS)
00977 {
00978 if(pres_db_delete_status(s)<0)
00979 {
00980 err_ret= -1;
00981 LM_ERR("failed to delete terminated dialog from database\n");
00982 goto done;
00983 }
00984 }
00985
00986 s= s->next;
00987 }
00988
00989 free_subs_list(subs_array, PKG_MEM_TYPE, 0);
00990 return 0;
00991
00992 done:
00993 if(result)
00994 pa_dbf.free_result(pa_db, result);
00995 free_subs_list(subs_array, PKG_MEM_TYPE, 0);
00996 if(ws_list)
00997 {
00998 for(i= 0; i< n; i++)
00999 {
01000 if(ws_list[i].w_user.s)
01001 pkg_free(ws_list[i].w_user.s);
01002 else
01003 break;
01004 if(ws_list[i].w_domain.s)
01005 pkg_free(ws_list[i].w_domain.s);
01006 if(ws_list[i].reason.s)
01007 pkg_free(ws_list[i].reason.s);
01008 }
01009 }
01010 return err_ret;
01011 }
01012
01013 static int update_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs_array)
01014 {
01015 subs_t* s, *ps, *cs;
01016 int i= 0;
01017
01018 LM_DBG("start\n");
01019 lock_get(&subs_htable[hash_code].lock);
01020
01021 ps= subs_htable[hash_code].entries;
01022
01023 while(ps && ps->next)
01024 {
01025 s= ps->next;
01026
01027 if(s->event== subs->event && s->pres_uri.len== subs->pres_uri.len &&
01028 s->from_user.len== subs->from_user.len &&
01029 s->from_domain.len==subs->from_domain.len &&
01030 strncmp(s->pres_uri.s, subs->pres_uri.s, subs->pres_uri.len)== 0 &&
01031 strncmp(s->from_user.s, subs->from_user.s, s->from_user.len)== 0 &&
01032 strncmp(s->from_domain.s,subs->from_domain.s,s->from_domain.len)==0)
01033 {
01034 i++;
01035 s->status= subs->status;
01036 s->reason= subs->reason;
01037 s->db_flag= UPDATEDB_FLAG;
01038
01039 cs= mem_copy_subs(s, PKG_MEM_TYPE);
01040 if(cs== NULL)
01041 {
01042 LM_ERR( "copying subs_t stucture\n");
01043 lock_release(&subs_htable[hash_code].lock);
01044 return -1;
01045 }
01046 cs->expires-= (int)time(NULL);
01047 cs->next= (*subs_array);
01048 (*subs_array)= cs;
01049 if(subs->status== TERMINATED_STATUS)
01050 {
01051 ps->next= s->next;
01052 shm_free(s->contact.s);
01053 shm_free(s);
01054 LM_DBG(" deleted terminated dialog from hash table\n");
01055 }
01056 else
01057 ps= s;
01058
01059 printf_subs(cs);
01060 }
01061 else
01062 ps= s;
01063 }
01064
01065 LM_DBG("found %d matching dialogs\n", i);
01066 lock_release(&subs_htable[hash_code].lock);
01067
01068 return 0;
01069 }