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
00035 #include "../../ut.h"
00036 #include "../../usr_avp.h"
00037 #include "../../data_lump_rpl.h"
00038 #include "../../parser/parse_expires.h"
00039 #include "../../parser/parse_event.h"
00040 #include "../../parser/contact/parse_contact.h"
00041 #include "../../hashes.h"
00042 #include "presence.h"
00043 #include "subscribe.h"
00044 #include "utils_func.h"
00045 #include "notify.h"
00046 #include "../pua/hash.h"
00047 #include "../../mod_fix.h"
00048
00049 int get_stored_info(struct sip_msg* msg, subs_t* subs, int* error_ret,
00050 str* reply_str);
00051 int get_database_info(struct sip_msg* msg, subs_t* subs, int* error_ret,
00052 str* reply_str);
00053 int get_db_subs_auth(subs_t* subs, int* found);
00054 int insert_db_subs_auth(subs_t* subs);
00055
00056 static str su_200_rpl = str_init("OK");
00057 static str pu_481_rpl = str_init("Subscription does not exist");
00058 static str pu_400_rpl = str_init("Bad request");
00059 static str pu_500_rpl = str_init("Server Internal Error");
00060 static str pu_489_rpl = str_init("Bad Event");
00061
00062 int send_2XX_reply(struct sip_msg * msg, int reply_code, int lexpire,
00063 str* local_contact)
00064 {
00065 str hdr_append = {0, 0};
00066 str tmp;
00067 char *t = NULL;
00068
00069 tmp.s = int2str((unsigned long)lexpire, &tmp.len);
00070 hdr_append.len = 9 + tmp.len + CRLF_LEN
00071 + 10 + local_contact->len + 16 + CRLF_LEN;
00072 hdr_append.s = (char *)pkg_malloc(sizeof(char)*(hdr_append.len+1));
00073 if(hdr_append.s == NULL)
00074 {
00075 ERR_MEM(PKG_MEM_STR);
00076 }
00077 strncpy(hdr_append.s, "Expires: ", 9);
00078 strncpy(hdr_append.s+9, tmp.s, tmp.len);
00079 tmp.s = hdr_append.s+9+tmp.len;
00080 strncpy(tmp.s, CRLF, CRLF_LEN);
00081 tmp.s += CRLF_LEN;
00082 strncpy(tmp.s, "Contact: <", 10);
00083 tmp.s += 10;
00084 strncpy(tmp.s, local_contact->s, local_contact->len);
00085 tmp.s[local_contact->len] = '\0';
00086 t = strstr(tmp.s, ";transport=");
00087 tmp.s += local_contact->len;
00088 if(t==NULL)
00089 {
00090 switch (msg->rcv.proto)
00091 {
00092 case PROTO_TCP:
00093 strncpy(tmp.s, ";transport=tcp", 14);
00094 tmp.s += 14;
00095 hdr_append.len -= 1;
00096 break;
00097 case PROTO_TLS:
00098 strncpy(tmp.s, ";transport=tls", 14);
00099 tmp.s += 14;
00100 hdr_append.len -= 1;
00101 break;
00102 case PROTO_SCTP:
00103 strncpy(tmp.s, ";transport=sctp", 15);
00104 tmp.s += 15;
00105 break;
00106 default:
00107 hdr_append.len -= 15;
00108 }
00109 } else {
00110 hdr_append.len -= 15;
00111 }
00112 *tmp.s = '>';
00113 strncpy(tmp.s+1, CRLF, CRLF_LEN);
00114
00115 hdr_append.s[hdr_append.len]= '\0';
00116
00117 if (add_lump_rpl( msg, hdr_append.s, hdr_append.len, LUMP_RPL_HDR)==0 )
00118 {
00119 LM_ERR("unable to add lump_rl\n");
00120 goto error;
00121 }
00122
00123 if(slb.freply(msg, reply_code, &su_200_rpl) < 0)
00124 {
00125 LM_ERR("sending reply\n");
00126 goto error;
00127 }
00128
00129 pkg_free(hdr_append.s);
00130 return 0;
00131
00132 error:
00133
00134 if(hdr_append.s!=NULL)
00135 pkg_free(hdr_append.s);
00136 return -1;
00137 }
00138
00139
00140 int delete_db_subs(str* to_tag, str* from_tag, str* callid)
00141 {
00142 db_key_t query_cols[3];
00143 db_val_t query_vals[3];
00144 int n_query_cols= 0;
00145
00146 query_cols[n_query_cols] = &str_callid_col;
00147 query_vals[n_query_cols].type = DB1_STR;
00148 query_vals[n_query_cols].nul = 0;
00149 query_vals[n_query_cols].val.str_val = *callid;
00150 n_query_cols++;
00151
00152 query_cols[n_query_cols] = &str_to_tag_col;
00153 query_vals[n_query_cols].type = DB1_STR;
00154 query_vals[n_query_cols].nul = 0;
00155 query_vals[n_query_cols].val.str_val = *to_tag;
00156 n_query_cols++;
00157
00158 query_cols[n_query_cols] = &str_from_tag_col;
00159 query_vals[n_query_cols].type = DB1_STR;
00160 query_vals[n_query_cols].nul = 0;
00161 query_vals[n_query_cols].val.str_val = *from_tag;
00162 n_query_cols++;
00163
00164 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
00165 {
00166 LM_ERR("in use table sql operation\n");
00167 return -1;
00168 }
00169
00170 if(pa_dbf.delete(pa_db, query_cols, 0, query_vals,
00171 n_query_cols)< 0 )
00172 {
00173 LM_ERR("sql delete failed\n");
00174 return -1;
00175 }
00176
00177 return 0;
00178 }
00179
00180 int insert_subs_db(subs_t* s, int type)
00181 {
00182 db_key_t query_cols[24];
00183 db_val_t query_vals[24];
00184 int n_query_cols = 0;
00185 int pres_uri_col, to_user_col, to_domain_col, from_user_col, from_domain_col,
00186 callid_col, totag_col, fromtag_col, event_col,status_col, event_id_col,
00187 local_cseq_col, remote_cseq_col, expires_col, record_route_col,
00188 contact_col, local_contact_col, version_col,socket_info_col,reason_col,
00189 watcher_user_col, watcher_domain_col, updated_col, updated_winfo_col;
00190
00191 if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
00192 {
00193 LM_ERR("sql use table failed\n");
00194 return -1;
00195 }
00196
00197 query_cols[pres_uri_col= n_query_cols] =&str_presentity_uri_col;
00198 query_vals[pres_uri_col].type = DB1_STR;
00199 query_vals[pres_uri_col].nul = 0;
00200 n_query_cols++;
00201
00202 query_cols[callid_col= n_query_cols] =&str_callid_col;
00203 query_vals[callid_col].type = DB1_STR;
00204 query_vals[callid_col].nul = 0;
00205 n_query_cols++;
00206
00207 query_cols[totag_col= n_query_cols] =&str_to_tag_col;
00208 query_vals[totag_col].type = DB1_STR;
00209 query_vals[totag_col].nul = 0;
00210 n_query_cols++;
00211
00212 query_cols[fromtag_col= n_query_cols] =&str_from_tag_col;
00213 query_vals[fromtag_col].type = DB1_STR;
00214 query_vals[fromtag_col].nul = 0;
00215 n_query_cols++;
00216
00217 query_cols[to_user_col= n_query_cols] =&str_to_user_col;
00218 query_vals[to_user_col].type = DB1_STR;
00219 query_vals[to_user_col].nul = 0;
00220 n_query_cols++;
00221
00222 query_cols[to_domain_col= n_query_cols] =&str_to_domain_col;
00223 query_vals[to_domain_col].type = DB1_STR;
00224 query_vals[to_domain_col].nul = 0;
00225 n_query_cols++;
00226
00227 query_cols[from_user_col= n_query_cols] =&str_from_user_col;
00228 query_vals[from_user_col].type = DB1_STR;
00229 query_vals[from_user_col].nul = 0;
00230 n_query_cols++;
00231
00232 query_cols[from_domain_col= n_query_cols] =&str_from_domain_col;
00233 query_vals[from_domain_col].type = DB1_STR;
00234 query_vals[from_domain_col].nul = 0;
00235 n_query_cols++;
00236
00237 query_cols[watcher_user_col= n_query_cols] =&str_watcher_username_col;
00238 query_vals[watcher_user_col].type = DB1_STR;
00239 query_vals[watcher_user_col].nul = 0;
00240 n_query_cols++;
00241
00242 query_cols[watcher_domain_col= n_query_cols] =&str_watcher_domain_col;
00243 query_vals[watcher_domain_col].type = DB1_STR;
00244 query_vals[watcher_domain_col].nul = 0;
00245 n_query_cols++;
00246
00247 query_cols[event_col= n_query_cols] =&str_event_col;
00248 query_vals[event_col].type = DB1_STR;
00249 query_vals[event_col].nul = 0;
00250 n_query_cols++;
00251
00252 query_cols[event_id_col= n_query_cols] =&str_event_id_col;
00253 query_vals[event_id_col].type = DB1_STR;
00254 query_vals[event_id_col].nul = 0;
00255 n_query_cols++;
00256
00257 query_cols[local_cseq_col= n_query_cols]=&str_local_cseq_col;
00258 query_vals[local_cseq_col].type = DB1_INT;
00259 query_vals[local_cseq_col].nul = 0;
00260 n_query_cols++;
00261
00262 query_cols[remote_cseq_col= n_query_cols]=&str_remote_cseq_col;
00263 query_vals[remote_cseq_col].type = DB1_INT;
00264 query_vals[remote_cseq_col].nul = 0;
00265 n_query_cols++;
00266
00267 query_cols[expires_col= n_query_cols] =&str_expires_col;
00268 query_vals[expires_col].type = DB1_INT;
00269 query_vals[expires_col].nul = 0;
00270 n_query_cols++;
00271
00272 query_cols[status_col= n_query_cols] =&str_status_col;
00273 query_vals[status_col].type = DB1_INT;
00274 query_vals[status_col].nul = 0;
00275 n_query_cols++;
00276
00277 query_cols[reason_col= n_query_cols] =&str_reason_col;
00278 query_vals[reason_col].type = DB1_STR;
00279 query_vals[reason_col].nul = 0;
00280 n_query_cols++;
00281
00282 query_cols[record_route_col= n_query_cols] =&str_record_route_col;
00283 query_vals[record_route_col].type = DB1_STR;
00284 query_vals[record_route_col].nul = 0;
00285 n_query_cols++;
00286
00287 query_cols[contact_col= n_query_cols] =&str_contact_col;
00288 query_vals[contact_col].type = DB1_STR;
00289 query_vals[contact_col].nul = 0;
00290 n_query_cols++;
00291
00292 query_cols[local_contact_col= n_query_cols] =&str_local_contact_col;
00293 query_vals[local_contact_col].type = DB1_STR;
00294 query_vals[local_contact_col].nul = 0;
00295 n_query_cols++;
00296
00297 query_cols[socket_info_col= n_query_cols] =&str_socket_info_col;
00298 query_vals[socket_info_col].type = DB1_STR;
00299 query_vals[socket_info_col].nul = 0;
00300 n_query_cols++;
00301
00302 query_cols[version_col= n_query_cols]=&str_version_col;
00303 query_vals[version_col].type = DB1_INT;
00304 query_vals[version_col].nul = 0;
00305 n_query_cols++;
00306
00307 query_cols[updated_col= n_query_cols]=&str_updated_col;
00308 query_vals[updated_col].type = DB1_INT;
00309 query_vals[updated_col].nul = 0;
00310 n_query_cols++;
00311
00312 query_cols[updated_winfo_col= n_query_cols]=&str_updated_winfo_col;
00313 query_vals[updated_winfo_col].type = DB1_INT;
00314 query_vals[updated_winfo_col].nul = 0;
00315 n_query_cols++;
00316
00317 query_vals[pres_uri_col].val.str_val= s->pres_uri;
00318 query_vals[callid_col].val.str_val= s->callid;
00319 query_vals[totag_col].val.str_val= s->to_tag;
00320 query_vals[fromtag_col].val.str_val= s->from_tag;
00321 query_vals[to_user_col].val.str_val = s->to_user;
00322 query_vals[to_domain_col].val.str_val = s->to_domain;
00323 query_vals[from_user_col].val.str_val = s->from_user;
00324 query_vals[from_domain_col].val.str_val = s->from_domain;
00325 query_vals[watcher_user_col].val.str_val = s->watcher_user;
00326 query_vals[watcher_domain_col].val.str_val = s->watcher_domain;
00327 query_vals[event_col].val.str_val = s->event->name;
00328 query_vals[event_id_col].val.str_val = s->event_id;
00329 query_vals[local_cseq_col].val.int_val= s->local_cseq;
00330 query_vals[remote_cseq_col].val.int_val= s->remote_cseq;
00331 query_vals[expires_col].val.int_val = s->expires + (int)time(NULL);
00332 query_vals[record_route_col].val.str_val = s->record_route;
00333 query_vals[contact_col].val.str_val = s->contact;
00334 query_vals[local_contact_col].val.str_val = s->local_contact;
00335 query_vals[version_col].val.int_val= s->version;
00336 query_vals[status_col].val.int_val= s->status;
00337 query_vals[reason_col].val.str_val= s->reason;
00338 query_vals[socket_info_col].val.str_val= s->sockinfo_str;
00339 query_vals[updated_col].val.int_val = s->updated;
00340 query_vals[updated_winfo_col].val.int_val = s->updated_winfo;
00341
00342 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
00343 {
00344 LM_ERR("in use table sql operation\n");
00345 return -1;
00346 }
00347
00348 LM_DBG("inserting subscription in active_watchers table\n");
00349 if(pa_dbf.insert(pa_db, query_cols, query_vals, n_query_cols) < 0)
00350 {
00351 LM_ERR("unsuccessful sql insert\n");
00352 return -1;
00353 }
00354 return 0;
00355 }
00356
00357 int update_subs_db(subs_t* subs, int type)
00358 {
00359 db_key_t query_cols[3], update_keys[8];
00360 db_val_t query_vals[3], update_vals[8];
00361 int n_update_cols= 0;
00362 int n_query_cols = 0;
00363
00364 query_cols[n_query_cols] = &str_callid_col;
00365 query_vals[n_query_cols].type = DB1_STR;
00366 query_vals[n_query_cols].nul = 0;
00367 query_vals[n_query_cols].val.str_val = subs->callid;
00368 n_query_cols++;
00369
00370 query_cols[n_query_cols] = &str_to_tag_col;
00371 query_vals[n_query_cols].type = DB1_STR;
00372 query_vals[n_query_cols].nul = 0;
00373 query_vals[n_query_cols].val.str_val = subs->to_tag;
00374 n_query_cols++;
00375
00376 query_cols[n_query_cols] = &str_from_tag_col;
00377 query_vals[n_query_cols].type = DB1_STR;
00378 query_vals[n_query_cols].nul = 0;
00379 query_vals[n_query_cols].val.str_val = subs->from_tag;
00380 n_query_cols++;
00381
00382 if(type & REMOTE_TYPE)
00383 {
00384 update_keys[n_update_cols] = &str_expires_col;
00385 update_vals[n_update_cols].type = DB1_INT;
00386 update_vals[n_update_cols].nul = 0;
00387 update_vals[n_update_cols].val.int_val = subs->expires + (int)time(NULL);
00388 n_update_cols++;
00389
00390 update_keys[n_update_cols] = &str_remote_cseq_col;
00391 update_vals[n_update_cols].type = DB1_INT;
00392 update_vals[n_update_cols].nul = 0;
00393 update_vals[n_update_cols].val.int_val = subs->remote_cseq;
00394 n_update_cols++;
00395
00396 update_keys[n_update_cols] = &str_updated_col;
00397 update_vals[n_update_cols].type = DB1_INT;
00398 update_vals[n_update_cols].nul = 0;
00399 update_vals[n_update_cols].val.int_val = subs->updated;
00400 n_update_cols++;
00401
00402 update_keys[n_update_cols] = &str_updated_winfo_col;
00403 update_vals[n_update_cols].type = DB1_INT;
00404 update_vals[n_update_cols].nul = 0;
00405 update_vals[n_update_cols].val.int_val = subs->updated_winfo;
00406 n_update_cols++;
00407 }
00408 if(type & LOCAL_TYPE)
00409 {
00410 update_keys[n_update_cols] = &str_local_cseq_col;
00411 update_vals[n_update_cols].type = DB1_INT;
00412 update_vals[n_update_cols].nul = 0;
00413 update_vals[n_update_cols].val.int_val = subs->local_cseq;
00414 n_update_cols++;
00415
00416 update_keys[n_update_cols] = &str_version_col;
00417 update_vals[n_update_cols].type = DB1_INT;
00418 update_vals[n_update_cols].nul = 0;
00419 update_vals[n_update_cols].val.int_val = subs->version;
00420 n_update_cols++;
00421 }
00422
00423 update_keys[n_update_cols] = &str_status_col;
00424 update_vals[n_update_cols].type = DB1_INT;
00425 update_vals[n_update_cols].nul = 0;
00426 update_vals[n_update_cols].val.int_val = subs->status;
00427 n_update_cols++;
00428
00429 update_keys[n_update_cols] = &str_reason_col;
00430 update_vals[n_update_cols].type = DB1_STR;
00431 update_vals[n_update_cols].nul = 0;
00432 update_vals[n_update_cols].val.str_val = subs->reason;
00433 n_update_cols++;
00434
00435 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
00436 {
00437 LM_ERR("in use table sql operation\n");
00438 return -1;
00439 }
00440
00441 if( pa_dbf.update( pa_db,query_cols, 0, query_vals,
00442 update_keys, update_vals, n_query_cols,n_update_cols)<0)
00443 {
00444 LM_ERR("updating presence information\n");
00445 return -1;
00446 }
00447 return 0;
00448 }
00449
00450 void delete_subs(str* pres_uri, str* ev_name, str* to_tag,
00451 str* from_tag, str* callid)
00452 {
00453
00454 if(subs_dbmode != DB_ONLY)
00455 {
00456 unsigned int hash_code= core_hash(pres_uri, ev_name, shtable_size);
00457 if(delete_shtable(subs_htable, hash_code, *to_tag) < 0)
00458 LM_ERR("Failed to delete subscription from memory\n");
00459 }
00460
00461 if(subs_dbmode != NO_DB && delete_db_subs(to_tag, from_tag, callid)< 0)
00462 LM_ERR("Failed to delete subscription from database\n");
00463 }
00464
00465 int update_subscription_notifier(struct sip_msg* msg, subs_t* subs,
00466 int to_tag_gen, int* sent_reply)
00467 {
00468 int num_peers = 0;
00469
00470 *sent_reply= 0;
00471
00472
00473 subs->updated = core_hash(&subs->callid, &subs->from_tag,
00474 (pres_waitn_time * pres_notifier_poll_rate
00475 * pres_notifier_processes) - 1);
00476 if (subs->event->type & WINFO_TYPE)
00477 subs->updated_winfo = UPDATED_TYPE;
00478 else if (subs->event->wipeer)
00479 {
00480 if ((num_peers = set_wipeer_subs_updated(&subs->pres_uri,
00481 subs->event->wipeer,
00482 subs->expires == 0)) < 0)
00483 {
00484 LM_ERR("failed to update database record(s)\n");
00485 goto error;
00486 }
00487
00488 if (num_peers > 0)
00489 subs->updated_winfo = UPDATED_TYPE;
00490 }
00491 if (subs->expires == 0)
00492 {
00493 subs->status = TERMINATED_STATUS;
00494 subs->reason.s = "timeout";
00495 subs->reason.len = 7;
00496 }
00497
00498 printf_subs(subs);
00499
00500 if (to_tag_gen == 0)
00501 {
00502 if (update_subs_db(subs, REMOTE_TYPE) < 0)
00503 {
00504 LM_ERR("updating subscription in database table\n");
00505 goto error;
00506 }
00507 }
00508 else
00509 {
00510 subs->version = 1;
00511 if (insert_subs_db(subs, REMOTE_TYPE) < 0)
00512 {
00513 LM_ERR("failed to insert new record in database\n");
00514 goto error;
00515 }
00516 }
00517
00518 if(send_2XX_reply(msg, subs->event->type & PUBL_TYPE ? 202 : 200,
00519 subs->expires, &subs->local_contact) < 0)
00520 {
00521 LM_ERR("sending %d response\n",
00522 subs->event->type & PUBL_TYPE ? 202 : 200);
00523 goto error;
00524 }
00525 *sent_reply= 1;
00526
00527 return 1;
00528
00529 error:
00530 return -1;
00531 }
00532
00533 int update_subscription(struct sip_msg* msg, subs_t* subs, int to_tag_gen,
00534 int* sent_reply)
00535 {
00536 unsigned int hash_code;
00537
00538 LM_DBG("update subscription\n");
00539 printf_subs(subs);
00540
00541 *sent_reply= 0;
00542
00543 if( to_tag_gen ==0)
00544 {
00545 if(subs->expires == 0)
00546 {
00547 LM_DBG("expires =0 -> deleting record\n");
00548
00549 delete_subs(&subs->pres_uri, &subs->event->name, &subs->to_tag,
00550 &subs->from_tag, &subs->callid);
00551
00552 if(subs->event->type & PUBL_TYPE)
00553 {
00554 if( send_2XX_reply(msg, 202, subs->expires,
00555 &subs->local_contact) <0)
00556 {
00557 LM_ERR("sending 202 OK\n");
00558 goto error;
00559 }
00560 *sent_reply= 1;
00561 if(subs->event->wipeer)
00562 {
00563 if(query_db_notify(&subs->pres_uri,
00564 subs->event->wipeer, NULL)< 0)
00565 {
00566 LM_ERR("Could not send notify for winfo\n");
00567 goto error;
00568 }
00569 }
00570
00571 }
00572 else
00573 {
00574 if( send_2XX_reply(msg, 200, subs->expires,
00575 &subs->local_contact) <0)
00576 {
00577 LM_ERR("sending 200 OK reply\n");
00578 goto error;
00579 }
00580 *sent_reply= 1;
00581 }
00582
00583 if(notify(subs, NULL, NULL, 0)< 0)
00584 {
00585 LM_ERR("Could not send notify\n");
00586 goto error;
00587 }
00588 return 1;
00589 }
00590
00591 if(subs_dbmode != DB_ONLY)
00592 {
00593 hash_code= core_hash(&subs->pres_uri, &subs->event->name, shtable_size);
00594 if(update_shtable(subs_htable, hash_code, subs, REMOTE_TYPE)< 0)
00595 {
00596 LM_ERR("failed to update subscription in memory\n");
00597 goto error;
00598 }
00599 }
00600
00601 if(subs_dbmode == DB_ONLY || subs_dbmode== WRITE_THROUGH)
00602 {
00603
00604 if(update_subs_db(subs, REMOTE_TYPE|LOCAL_TYPE)< 0)
00605 {
00606 LM_ERR("updating subscription in database table\n");
00607 goto error;
00608 }
00609 }
00610 }
00611 else
00612 {
00613 LM_DBG("subscription not in dialog\n");
00614 if(subs->expires!= 0)
00615 {
00616 if(subs_dbmode != DB_ONLY)
00617 {
00618 LM_DBG("inserting in shtable\n");
00619 subs->db_flag = (subs_dbmode==WRITE_THROUGH)?WTHROUGHDB_FLAG:INSERTDB_FLAG;
00620 hash_code= core_hash(&subs->pres_uri, &subs->event->name, shtable_size);
00621 subs->version = 0;
00622 if(insert_shtable(subs_htable,hash_code,subs)< 0)
00623 {
00624 LM_ERR("failed to insert new record in subs htable\n");
00625 goto error;
00626 }
00627 }
00628
00629 if(subs_dbmode == DB_ONLY || subs_dbmode == WRITE_THROUGH)
00630 {
00631 subs->version = 1;
00632 if(insert_subs_db(subs, REMOTE_TYPE) < 0)
00633 {
00634 LM_ERR("failed to insert new record in database\n");
00635 goto error;
00636 }
00637 }
00638
00639 }
00640
00641
00642 else
00643 {
00644 LM_DBG("subscription request with expiry=0 not in dialog\n");
00645 }
00646 }
00647
00648
00649
00650 if(subs->event->type & PUBL_TYPE)
00651 {
00652 if(send_2XX_reply(msg, 202, subs->expires,
00653 &subs->local_contact)<0)
00654 {
00655 LM_ERR("sending 202 OK reply\n");
00656 goto error;
00657 }
00658 *sent_reply= 1;
00659
00660 if(subs->expires!= 0 && subs->event->wipeer)
00661 {
00662 LM_DBG("send Notify with winfo\n");
00663 if(query_db_notify(&subs->pres_uri, subs->event->wipeer, subs)< 0)
00664 {
00665 LM_ERR("Could not send notify winfo\n");
00666 goto error;
00667 }
00668 if(subs->send_on_cback== 0)
00669 {
00670 if(notify(subs, NULL, NULL, 0)< 0)
00671 {
00672 LM_ERR("Could not send notify\n");
00673 goto error;
00674 }
00675 }
00676 }
00677 else
00678 {
00679 if(notify(subs, NULL, NULL, 0)< 0)
00680 {
00681 LM_ERR("Could not send notify\n");
00682 goto error;
00683 }
00684 }
00685
00686 }
00687 else
00688 {
00689 if( send_2XX_reply(msg, 200, subs->expires,
00690 &subs->local_contact)<0)
00691 {
00692 LM_ERR("sending 200 OK reply\n");
00693 goto error;
00694 }
00695 *sent_reply= 1;
00696
00697 if(send_fast_notify && (notify(subs, NULL, NULL, 0 )< 0))
00698 {
00699 LM_ERR("sending notify request\n");
00700 goto error;
00701 }
00702 }
00703 return 0;
00704
00705 error:
00706
00707 LM_ERR("occured\n");
00708 return -1;
00709
00710 }
00711
00712 void msg_watchers_clean(unsigned int ticks,void *param)
00713 {
00714 db_key_t db_keys[2];
00715 db_val_t db_vals[2];
00716 db_op_t db_ops[2] ;
00717
00718 LM_DBG("cleaning pending subscriptions\n");
00719
00720 db_keys[0] = &str_inserted_time_col;
00721 db_ops[0] = OP_LT;
00722 db_vals[0].type = DB1_INT;
00723 db_vals[0].nul = 0;
00724 db_vals[0].val.int_val = (int)time(NULL)- 24*3600 ;
00725
00726 db_keys[1] = &str_status_col;
00727 db_ops [1] = OP_EQ;
00728 db_vals[1].type = DB1_INT;
00729 db_vals[1].nul = 0;
00730 db_vals[1].val.int_val = PENDING_STATUS;
00731
00732 if (pa_dbf.use_table(pa_db, &watchers_table) < 0)
00733 {
00734 LM_ERR("unsuccessful use table sql operation\n");
00735 return ;
00736 }
00737
00738 if (pa_dbf.delete(pa_db, db_keys, db_ops, db_vals, 2) < 0)
00739 LM_ERR("cleaning pending subscriptions\n");
00740 }
00741
00742 int handle_subscribe0(struct sip_msg* msg)
00743 {
00744 struct to_body *pfrom;
00745
00746 if (parse_from_uri(msg) < 0)
00747 {
00748 LM_ERR("failed to find From header\n");
00749 if (slb.freply(msg, 400, &pu_400_rpl) < 0)
00750 {
00751 LM_ERR("while sending 400 reply\n");
00752 return -1;
00753 }
00754 return 0;
00755 }
00756 pfrom = (struct to_body *) msg->from->parsed;
00757
00758 return handle_subscribe(msg, pfrom->parsed_uri.user,
00759 pfrom->parsed_uri.host);
00760 }
00761
00762 int w_handle_subscribe(struct sip_msg* msg, char* watcher_uri)
00763 {
00764 str wuri;
00765 struct sip_uri parsed_wuri;
00766
00767 if (fixup_get_svalue(msg, (gparam_p)watcher_uri, &wuri) != 0)
00768 {
00769 LM_ERR("invalid uri parameter\n");
00770 return -1;
00771 }
00772
00773 if (parse_uri(wuri.s, wuri.len, &parsed_wuri) < 0)
00774 {
00775 LM_ERR("failed to parse watcher URI\n");
00776 return -1;
00777 }
00778
00779 return handle_subscribe(msg, parsed_wuri.user, parsed_wuri.host);
00780 }
00781
00782 int handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain)
00783 {
00784 int to_tag_gen = 0;
00785 subs_t subs;
00786 pres_ev_t* event= NULL;
00787 event_t* parsed_event= NULL;
00788 param_t* ev_param= NULL;
00789 int found;
00790 str reason= {0, 0};
00791 struct sip_uri uri;
00792 int reply_code;
00793 str reply_str;
00794 int sent_reply= 0;
00795
00796
00797 counter++;
00798
00799 memset(&subs, 0, sizeof(subs_t));
00800
00801 reply_code= 500;
00802 reply_str= pu_500_rpl;
00803
00804 if(parse_headers(msg,HDR_EOH_F, 0) == -1)
00805 {
00806 LM_ERR("parsing headers\n");
00807 reply_code= 400;
00808 reply_str= pu_400_rpl;
00809 goto error;
00810 }
00811
00812
00813 if(msg->event && msg->event->body.len > 0)
00814 {
00815 if (!msg->event->parsed && (parse_event(msg->event) < 0))
00816 {
00817 reply_code= 400;
00818 reply_str= pu_400_rpl;
00819 goto error;
00820 }
00821 }
00822 else
00823 goto bad_event;
00824
00825
00826 parsed_event= (event_t*)msg->event->parsed;
00827 event= search_event(parsed_event);
00828 if(event== NULL)
00829 {
00830 goto bad_event;
00831 }
00832 subs.event= event;
00833
00834
00835 ev_param= parsed_event->params.list;
00836 while(ev_param)
00837 {
00838 if(ev_param->name.len== 2 && strncmp(ev_param->name.s, "id", 2)== 0)
00839 {
00840 subs.event_id= ev_param->body;
00841 break;
00842 }
00843 ev_param= ev_param->next;
00844 }
00845
00846 if(extract_sdialog_info(&subs, msg, max_expires, &to_tag_gen,
00847 server_address, watcher_user, watcher_domain)< 0)
00848 {
00849 LM_ERR("failed to extract dialog information\n");
00850 goto error;
00851 }
00852
00853
00854 if(to_tag_gen)
00855 {
00856 if (!EVENT_DIALOG_SLA(parsed_event))
00857 {
00858 if( parse_sip_msg_uri(msg)< 0)
00859 {
00860 LM_ERR("failed to parse R-URI\n");
00861 return -1;
00862 }
00863 if(uandd_to_uri(msg->parsed_uri.user, msg->parsed_uri.host,
00864 &subs.pres_uri)< 0)
00865 {
00866 LM_ERR("failed to construct uri from user and domain\n");
00867 goto error;
00868 }
00869 }
00870 }
00871 else
00872 {
00873 if(get_stored_info(msg, &subs, &reply_code, &reply_str )< 0)
00874 {
00875 LM_INFO("getting stored info\n");
00876 goto error;
00877 }
00878 reason= subs.reason;
00879 }
00880
00881 subs.recv_event = PRES_SUBSCRIBE_RECV;
00882
00883
00884 if(event->evs_subs_handl)
00885 {
00886 if(event->evs_subs_handl(msg)< 0)
00887 {
00888 LM_ERR("in event specific subscription handling\n");
00889 goto error;
00890 }
00891 }
00892
00893
00894
00895 if(to_tag_gen)
00896 {
00897 subs.updated = NO_UPDATE_TYPE;
00898 subs.updated_winfo = NO_UPDATE_TYPE;
00899
00900 if(!event->req_auth)
00901 subs.status = ACTIVE_STATUS;
00902 else
00903 {
00904
00905 if(get_db_subs_auth(&subs, &found)< 0)
00906 {
00907 LM_ERR("getting subscription status from watchers table\n");
00908 goto error;
00909 }
00910 if(found== 0)
00911 {
00912
00913 subs.status= PENDING_STATUS;
00914 subs.reason.s= NULL;
00915 subs.reason.len= 0;
00916
00917
00918 if(parse_uri(subs.pres_uri.s, subs.pres_uri.len, &uri)< 0)
00919 {
00920 LM_ERR("parsing uri\n");
00921 goto error;
00922
00923 }
00924 if(subs.event->get_rules_doc(&uri.user, &uri.host, &subs.auth_rules_doc)< 0)
00925 {
00926 LM_ERR("getting rules doc\n");
00927 goto error;
00928 }
00929
00930 if(subs.event->get_auth_status(&subs)< 0)
00931 {
00932 LM_ERR("in event specific function is_watcher_allowed\n");
00933 goto error;
00934 }
00935 if(get_status_str(subs.status) == NULL)
00936 {
00937 LM_ERR("wrong status= %d\n", subs.status);
00938 goto error;
00939 }
00940
00941 if(insert_db_subs_auth(&subs)< 0)
00942 {
00943 LM_ERR("while inserting record in watchers table\n");
00944 goto error;
00945 }
00946 }
00947 else
00948 {
00949 reason= subs.reason;
00950 }
00951 }
00952 }
00953
00954
00955 if(get_status_str(subs.status)== NULL)
00956 {
00957 LM_ERR("wrong status\n");
00958 goto error;
00959 }
00960 LM_DBG("subscription status= %s - %s\n", get_status_str(subs.status),
00961 found==0?"inserted":"found in watcher table");
00962
00963 if (pres_notifier_processes > 0)
00964 {
00965 if (update_subscription_notifier(msg, &subs, to_tag_gen,
00966 &sent_reply) < 0)
00967 {
00968 LM_ERR("in update_subscription_notifier\n");
00969 goto error;
00970 }
00971 }
00972 else if (update_subscription(msg, &subs, to_tag_gen, &sent_reply) <0)
00973 {
00974 LM_ERR("in update_subscription\n");
00975 goto error;
00976 }
00977 if(subs.auth_rules_doc)
00978 {
00979 pkg_free(subs.auth_rules_doc->s);
00980 pkg_free(subs.auth_rules_doc);
00981 }
00982 if(reason.s)
00983 pkg_free(reason.s);
00984
00985 if(subs.pres_uri.s)
00986 pkg_free(subs.pres_uri.s);
00987
00988 if((!server_address.s) || (server_address.len== 0))
00989 {
00990 pkg_free(subs.local_contact.s);
00991 }
00992 if(subs.record_route.s)
00993 pkg_free(subs.record_route.s);
00994
00995 return 1;
00996
00997 bad_event:
00998
00999 if (parsed_event && parsed_event->name.s)
01000 LM_ERR("Unsupported event header field value %.*s\n",
01001 parsed_event->name.len,parsed_event->name.s);
01002 else
01003 LM_ERR("Missing event header field value\n");
01004
01005 reply_code= BAD_EVENT_CODE;
01006 reply_str= pu_489_rpl;
01007
01008 error:
01009
01010 if(sent_reply== 0)
01011 {
01012 if(send_error_reply(msg, reply_code, reply_str)< 0)
01013 {
01014 LM_ERR("failed to send reply on error case\n");
01015 }
01016 }
01017
01018 if(subs.pres_uri.s)
01019 pkg_free(subs.pres_uri.s);
01020
01021 if(subs.auth_rules_doc)
01022 {
01023 if(subs.auth_rules_doc->s)
01024 pkg_free(subs.auth_rules_doc->s);
01025 pkg_free(subs.auth_rules_doc);
01026 }
01027 if(reason.s)
01028 pkg_free(reason.s);
01029
01030 if(((!server_address.s) ||(server_address.len== 0))&& subs.local_contact.s)
01031 {
01032 pkg_free(subs.local_contact.s);
01033 }
01034 if(subs.record_route.s)
01035 pkg_free(subs.record_route.s);
01036
01037 return -1;
01038
01039 }
01040
01041
01042 int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int mexp,
01043 int* to_tag_gen, str scontact, str watcher_user,
01044 str watcher_domain)
01045 {
01046 str rec_route= {0, 0};
01047 int rt = 0;
01048 contact_body_t *b;
01049 struct to_body *pto, TO = {0}, *pfrom = NULL;
01050 int lexpire;
01051 str rtag_value;
01052 struct sip_uri uri;
01053
01054
01055 if(msg->expires && msg->expires->body.len > 0)
01056 {
01057 if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
01058 {
01059 LM_ERR("cannot parse Expires header\n");
01060 goto error;
01061 }
01062 lexpire = ((exp_body_t*)msg->expires->parsed)->val;
01063 LM_DBG("'Expires' header found, value= %d\n", lexpire);
01064
01065 }
01066 else
01067 {
01068 LM_DBG("'expires' not found; default=%d\n",subs->event->default_expires);
01069 lexpire = subs->event->default_expires;
01070 }
01071 if(lexpire > mexp)
01072 lexpire = mexp;
01073
01074 subs->expires = lexpire;
01075
01076 if( msg->to==NULL || msg->to->body.s==NULL)
01077 {
01078 LM_ERR("cannot parse TO header\n");
01079 goto error;
01080 }
01081
01082 if(msg->to->parsed != NULL)
01083 {
01084 pto = (struct to_body*)msg->to->parsed;
01085 LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",pto->uri.len,pto->uri.s);
01086 }
01087 else
01088 {
01089 parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO);
01090 if( TO.uri.len <= 0 )
01091 {
01092 LM_DBG("'To' header NOT parsed\n");
01093 goto error;
01094 }
01095 pto = &TO;
01096 }
01097
01098 if( pto->parsed_uri.user.s && pto->parsed_uri.host.s &&
01099 pto->parsed_uri.user.len && pto->parsed_uri.host.len)
01100 {
01101 subs->to_user = pto->parsed_uri.user;
01102 subs->to_domain = pto->parsed_uri.host;
01103 }
01104 else
01105 {
01106 if(parse_uri(pto->uri.s, pto->uri.len, &uri)< 0)
01107 {
01108 LM_ERR("while parsing uri\n");
01109 goto error;
01110 }
01111 subs->to_user = uri.user;
01112 subs->to_domain = uri.host;
01113 }
01114
01115
01116 if (!msg->from || !msg->from->body.s)
01117 {
01118 LM_DBG("cannot find 'from' header!\n");
01119 goto error;
01120 }
01121 if (msg->from->parsed == NULL)
01122 {
01123 LM_DBG("'From' header not parsed\n");
01124
01125 if ( parse_from_header( msg )<0 )
01126 {
01127 LM_DBG("cannot parse From header\n");
01128 goto error;
01129 }
01130 }
01131 pfrom = (struct to_body*)msg->from->parsed;
01132
01133 if( pfrom->parsed_uri.user.s && pfrom->parsed_uri.host.s &&
01134 pfrom->parsed_uri.user.len && pfrom->parsed_uri.host.len)
01135 {
01136 subs->from_user = pfrom->parsed_uri.user;
01137 subs->from_domain = pfrom->parsed_uri.host;
01138 }
01139 else
01140 {
01141 if(parse_uri(pfrom->uri.s, pfrom->uri.len, &uri)< 0)
01142 {
01143 LM_ERR("while parsing uri\n");
01144 goto error;
01145 }
01146 subs->from_user = uri.user;
01147 subs->from_domain = uri.host;
01148 }
01149
01150 subs->watcher_user = watcher_user;
01151 subs->watcher_domain = watcher_domain;
01152
01153
01154 if (pto->tag_value.s==NULL || pto->tag_value.len==0 )
01155 {
01156 LM_DBG("generating to_tag\n");
01157 *to_tag_gen = 1;
01158 rtag_value.len = 0;
01159 if(slb.get_reply_totag(msg, &rtag_value)<0 || rtag_value.len <= 0)
01160 {
01161 LM_ERR("while creating to_tag\n");
01162 goto error;
01163 }
01164 }
01165 else
01166 {
01167 *to_tag_gen = 0;
01168 rtag_value=pto->tag_value;
01169 }
01170 subs->to_tag = rtag_value;
01171
01172 if( msg->callid==NULL || msg->callid->body.s==NULL)
01173 {
01174 LM_ERR("cannot parse callid header\n");
01175 goto error;
01176 }
01177 subs->callid = msg->callid->body;
01178
01179 if( msg->cseq==NULL || msg->cseq->body.s==NULL)
01180 {
01181 LM_ERR("cannot parse cseq header\n");
01182 goto error;
01183 }
01184 if (str2int( &(get_cseq(msg)->number), &subs->remote_cseq)!=0 )
01185 {
01186 LM_ERR("cannot parse cseq number\n");
01187 goto error;
01188 }
01189 if( msg->contact==NULL || msg->contact->body.s==NULL)
01190 {
01191 LM_ERR("cannot parse contact header\n");
01192 goto error;
01193 }
01194 if( parse_contact(msg->contact) <0 )
01195 {
01196 LM_ERR(" cannot parse contact"
01197 " header\n");
01198 goto error;
01199 }
01200 b= (contact_body_t* )msg->contact->parsed;
01201
01202 if(b == NULL)
01203 {
01204 LM_ERR("cannot parse contact header\n");
01205 goto error;
01206 }
01207 if(b->star || b->contacts==NULL)
01208 {
01209 LM_ERR("Wrong contact header\n");
01210 goto error;
01211 }
01212
01213 subs->contact = b->contacts->uri;
01214
01215 LM_DBG("subs->contact= %.*s - len = %d\n",subs->contact.len,
01216 subs->contact.s, subs->contact.len);
01217
01218 if (EVENT_DIALOG_SLA(subs->event->evp))
01219 {
01220
01221 if(parse_uri(subs->contact.s, subs->contact.len, &uri)< 0)
01222 {
01223 LM_ERR("failed to parse contact uri\n");
01224 goto error;
01225 }
01226 if(uandd_to_uri(uri.user, subs->from_domain, &subs->pres_uri)< 0)
01227 {
01228 LM_ERR("failed to construct uri\n");
01229 goto error;
01230 }
01231 LM_DBG("&&&&&&&&&&&&&&& dialog pres_uri= %.*s\n",
01232 subs->pres_uri.len, subs->pres_uri.s);
01233 }
01234
01235
01236 if(*to_tag_gen && msg->record_route!=NULL)
01237 {
01238 rt = print_rr_body(msg->record_route, &rec_route, 0, 0);
01239 if(rt != 0)
01240 {
01241 LM_ERR("processing the record route [%d]\n", rt);
01242 rec_route.s=NULL;
01243 rec_route.len=0;
01244
01245 }
01246 }
01247 subs->record_route = rec_route;
01248
01249 subs->sockinfo_str= msg->rcv.bind_address->sock_str;
01250
01251 if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
01252 {
01253 LM_ERR("no from tag value present\n");
01254 goto error;
01255 }
01256 subs->from_tag = pfrom->tag_value;
01257
01258 subs->version = 1;
01259
01260 if((!scontact.s) || (scontact.len== 0))
01261 {
01262 if(ps_fill_local_contact(msg, &subs->local_contact)<0)
01263 {
01264 LM_ERR("cannot get local contact address\n");
01265 goto error;
01266 }
01267 }
01268 else
01269 subs->local_contact= scontact;
01270
01271 free_to_params(&TO);
01272 return 0;
01273
01274 error:
01275 free_to_params(&TO);
01276 return -1;
01277 }
01278
01279
01280 int get_stored_info(struct sip_msg* msg, subs_t* subs, int* reply_code,
01281 str* reply_str)
01282 {
01283 str pres_uri= {0, 0}, reason={0, 0};
01284 subs_t* s;
01285 int i;
01286 unsigned int hash_code;
01287
01288 if(subs_dbmode == DB_ONLY)
01289 return get_database_info(msg, subs, reply_code, reply_str);
01290
01291
01292 if(subs->pres_uri.s == NULL)
01293 {
01294 uandd_to_uri(subs->to_user, subs->to_domain, &pres_uri);
01295 if(pres_uri.s== NULL)
01296 {
01297 LM_ERR("creating uri from user and domain\n");
01298 return -1;
01299 }
01300 }
01301 else
01302 pres_uri = subs->pres_uri;
01303
01304 hash_code= core_hash(&pres_uri, &subs->event->name, shtable_size);
01305 lock_get(&subs_htable[hash_code].lock);
01306 s= search_shtable(subs_htable, subs->callid, subs->to_tag,
01307 subs->from_tag, hash_code);
01308 if(s)
01309 goto found_rec;
01310
01311 lock_release(&subs_htable[hash_code].lock);
01312
01313 if(subs->pres_uri.s)
01314 goto not_found;
01315
01316 pkg_free(pres_uri.s);
01317 pres_uri.s= NULL;
01318
01319 LM_DBG("record not found using R-URI search iteratively\n");
01320
01321 for(i= 0; i< shtable_size; i++)
01322 {
01323 lock_get(&subs_htable[i].lock);
01324 s= search_shtable(subs_htable, subs->callid,subs->to_tag,subs->from_tag, i);
01325 if (s)
01326 {
01327 pres_uri.s= (char*)pkg_malloc(s->pres_uri.len* sizeof(char));
01328 if(pres_uri.s== NULL)
01329 {
01330 lock_release(&subs_htable[i].lock);
01331 ERR_MEM(PKG_MEM_STR);
01332 }
01333 memcpy(pres_uri.s, s->pres_uri.s, s->pres_uri.len);
01334 pres_uri.len= s->pres_uri.len;
01335
01336 hash_code = i;
01337 break;
01338 }
01339 lock_release(&subs_htable[i].lock);
01340 }
01341
01342 if(!s)
01343 goto not_found;
01344
01345 found_rec:
01346
01347 LM_DBG("Record found in hash_table\n");
01348
01349 if(subs->pres_uri.s == NULL)
01350 subs->pres_uri= pres_uri;
01351
01352 subs->version = s->version + 1;
01353 subs->status= s->status;
01354 if(s->reason.s && s->reason.len)
01355 {
01356 reason.s= (char*)pkg_malloc(s->reason.len* sizeof(char));
01357 if(reason.s== NULL)
01358 {
01359 lock_release(&subs_htable[hash_code].lock);
01360 ERR_MEM(PKG_MEM_STR);
01361 }
01362 memcpy(reason.s, s->reason.s, s->reason.len);
01363 reason.len= s->reason.len;
01364 subs->reason= reason;
01365 }
01366 if(s->record_route.s && s->record_route.len)
01367 {
01368 subs->record_route.s= (char*)pkg_malloc
01369 (s->record_route.len* sizeof(char));
01370 if(subs->record_route.s== NULL)
01371 {
01372 lock_release(&subs_htable[hash_code].lock);
01373 ERR_MEM(PKG_MEM_STR);
01374 }
01375 memcpy(subs->record_route.s, s->record_route.s, s->record_route.len);
01376 subs->record_route.len= s->record_route.len;
01377 }
01378
01379 subs->local_cseq= s->local_cseq +1;
01380
01381 if(subs->remote_cseq<= s->remote_cseq)
01382 {
01383 LM_ERR("wrong sequence number;received: %d - stored: %d\n",
01384 subs->remote_cseq, s->remote_cseq);
01385
01386 *reply_code= 400;
01387 *reply_str= pu_400_rpl;
01388
01389 lock_release(&subs_htable[hash_code].lock);
01390 goto error;
01391 }
01392 lock_release(&subs_htable[hash_code].lock);
01393
01394 return 0;
01395
01396 not_found:
01397
01398 LM_INFO("record not found in hash_table\n");
01399 *reply_code= 481;
01400 *reply_str= pu_481_rpl;
01401
01402 return -1;
01403
01404 error:
01405 if(subs->reason.s)
01406 pkg_free(subs->reason.s);
01407 subs->reason.s= NULL;
01408 if(subs->record_route.s)
01409 pkg_free(subs->record_route.s);
01410 subs->record_route.s= NULL;
01411 return -1;
01412 }
01413
01414 int get_database_info(struct sip_msg* msg, subs_t* subs, int* reply_code, str* reply_str)
01415 {
01416 db_key_t query_cols[3];
01417 db_val_t query_vals[3];
01418 db_key_t result_cols[9];
01419 db1_res_t *result= NULL;
01420 db_row_t *row ;
01421 db_val_t *row_vals ;
01422 int n_query_cols = 0;
01423 int n_result_cols = 0;
01424 int remote_cseq_col= 0, local_cseq_col= 0, status_col, reason_col;
01425 int record_route_col, version_col, pres_uri_col;
01426 int updated_col, updated_winfo_col;
01427 unsigned int remote_cseq;
01428 str pres_uri, record_route;
01429 str reason;
01430
01431 query_cols[n_query_cols] = &str_callid_col;
01432 query_vals[n_query_cols].type = DB1_STR;
01433 query_vals[n_query_cols].nul = 0;
01434 query_vals[n_query_cols].val.str_val = subs->callid;
01435 n_query_cols++;
01436
01437 query_cols[n_query_cols] = &str_to_tag_col;
01438 query_vals[n_query_cols].type = DB1_STR;
01439 query_vals[n_query_cols].nul = 0;
01440 query_vals[n_query_cols].val.str_val = subs->to_tag;
01441 n_query_cols++;
01442
01443 query_cols[n_query_cols] = &str_from_tag_col;
01444 query_vals[n_query_cols].type = DB1_STR;
01445 query_vals[n_query_cols].nul = 0;
01446 query_vals[n_query_cols].val.str_val = subs->from_tag;
01447 n_query_cols++;
01448
01449 result_cols[pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
01450 result_cols[remote_cseq_col=n_result_cols++] = &str_remote_cseq_col;
01451 result_cols[local_cseq_col=n_result_cols++] = &str_local_cseq_col;
01452 result_cols[status_col=n_result_cols++] = &str_status_col;
01453 result_cols[reason_col=n_result_cols++] = &str_reason_col;
01454 result_cols[record_route_col=n_result_cols++] = &str_record_route_col;
01455 result_cols[version_col=n_result_cols++] = &str_version_col;
01456 result_cols[updated_col=n_result_cols++] = &str_updated_col;
01457 result_cols[updated_winfo_col=n_result_cols++] = &str_updated_winfo_col;
01458
01459 if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
01460 {
01461 LM_ERR("unsuccessful use_table sql operation\n");
01462 return -1;
01463 }
01464
01465 if (pa_dbf.query (pa_db, query_cols, 0, query_vals,
01466 result_cols, n_query_cols, n_result_cols, 0, &result) < 0)
01467 {
01468 LM_ERR("querying subscription dialog\n");
01469 if(result)
01470 pa_dbf.free_result(pa_db, result);
01471 return -1;
01472 }
01473 if(result== NULL)
01474 return -1;
01475
01476 if(result && result->n <=0)
01477 {
01478 LM_INFO("No matching subscription dialog found in database\n");
01479
01480 pa_dbf.free_result(pa_db, result);
01481 *reply_code= 481;
01482 *reply_str= pu_481_rpl;
01483
01484 return -1;
01485 }
01486
01487 row = &result->rows[0];
01488 row_vals = ROW_VALUES(row);
01489 remote_cseq= row_vals[remote_cseq_col].val.int_val;
01490
01491 if(subs->remote_cseq<= remote_cseq)
01492 {
01493 LM_ERR("wrong sequence number received: %d - stored: %d\n",
01494 subs->remote_cseq, remote_cseq);
01495 *reply_code= 400;
01496 *reply_str= pu_400_rpl;
01497 pa_dbf.free_result(pa_db, result);
01498 return -1;
01499 }
01500
01501 subs->status= row_vals[status_col].val.int_val;
01502 reason.s= (char*)row_vals[reason_col].val.string_val;
01503 if(reason.s)
01504 {
01505 reason.len= strlen(reason.s);
01506 subs->reason.s= (char*)pkg_malloc(reason.len* sizeof(char));
01507 if(subs->reason.s== NULL)
01508 {
01509 ERR_MEM(PKG_MEM_STR);
01510 }
01511 memcpy(subs->reason.s, reason.s, reason.len);
01512 subs->reason.len= reason.len;
01513 }
01514
01515 subs->local_cseq= row_vals[local_cseq_col].val.int_val + 1;
01516 subs->version= row_vals[version_col].val.int_val + 1;
01517
01518 if(!EVENT_DIALOG_SLA(subs->event->evp))
01519 {
01520 pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
01521 pres_uri.len= strlen(pres_uri.s);
01522 subs->pres_uri.s= (char*)pkg_malloc(pres_uri.len* sizeof(char));
01523 if(subs->pres_uri.s== NULL)
01524 {
01525 if(subs->reason.s)
01526 pkg_free(subs->reason.s);
01527 ERR_MEM(PKG_MEM_STR);
01528 }
01529 memcpy(subs->pres_uri.s, pres_uri.s, pres_uri.len);
01530 subs->pres_uri.len= pres_uri.len;
01531 }
01532
01533 record_route.s= (char*)row_vals[record_route_col].val.string_val;
01534 if(record_route.s)
01535 {
01536 record_route.len= strlen(record_route.s);
01537 subs->record_route.s= (char*)pkg_malloc(record_route.len*sizeof(char));
01538 if(subs->record_route.s== NULL)
01539 {
01540 ERR_MEM(PKG_MEM_STR);
01541 }
01542 memcpy(subs->record_route.s, record_route.s, record_route.len);
01543 subs->record_route.len= record_route.len;
01544 }
01545
01546 subs->updated= row_vals[updated_col].val.int_val;
01547 subs->updated_winfo= row_vals[updated_winfo_col].val.int_val;
01548
01549 pa_dbf.free_result(pa_db, result);
01550 result= NULL;
01551
01552 return 0;
01553 error:
01554 if(result)
01555 pa_dbf.free_result(pa_db, result);
01556
01557 return -1;
01558
01559 }
01560
01561
01562 int handle_expired_subs(subs_t* s)
01563 {
01564
01565
01566 s->status= TERMINATED_STATUS;
01567 s->reason.s= "timeout";
01568 s->reason.len= 7;
01569 s->expires= 0;
01570 s->local_cseq++;
01571
01572 if(send_notify_request(s, NULL, NULL, 1)< 0)
01573 {
01574 LM_ERR("send Notify not successful\n");
01575 return -1;
01576 }
01577
01578 return 0;
01579
01580 }
01581
01582 void update_db_subs_timer_notifier(void)
01583 {
01584 db_key_t query_cols[1], result_cols[3];
01585 db_val_t query_vals[1], *values;
01586 db_op_t query_ops[1];
01587 db_row_t *rows;
01588 db1_res_t *result = NULL;
01589 int n_query_cols = 0, n_result_cols = 0;
01590 int r_callid_col = 0, r_to_tag_col = 0, r_from_tag_col = 0;
01591 int i;
01592 subs_t subs;
01593
01594 if(pa_db == NULL)
01595 {
01596 LM_ERR("null database connection\n");
01597 goto error;
01598 }
01599
01600 if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
01601 {
01602 LM_ERR("use table failed\n");
01603 goto error;
01604 }
01605
01606 query_cols[n_query_cols]= &str_expires_col;
01607 query_vals[n_query_cols].type = DB1_INT;
01608 query_vals[n_query_cols].nul = 0;
01609 query_vals[n_query_cols].val.int_val= (int)time(NULL) - expires_offset;
01610 query_ops[n_query_cols]= OP_LT;
01611 n_query_cols++;
01612
01613 result_cols[r_callid_col=n_result_cols++] = &str_callid_col;
01614 result_cols[r_to_tag_col=n_result_cols++] = &str_to_tag_col;
01615 result_cols[r_from_tag_col=n_result_cols++] = &str_from_tag_col;
01616
01617 if(db_fetch_query(&pa_dbf, pres_fetch_rows, pa_db, query_cols,
01618 query_ops, query_vals, result_cols,
01619 n_query_cols, n_result_cols, 0, &result )< 0)
01620 {
01621 LM_ERR("Can't query db\n");
01622 goto error;
01623 }
01624
01625 if(result == NULL)
01626 {
01627 LM_ERR("bad result\n");
01628 goto error;
01629 }
01630
01631 do {
01632 rows = RES_ROWS(result);
01633
01634 for (i = 0; i <RES_ROW_N(result); i++)
01635 {
01636 values = ROW_VALUES(&rows[i]);
01637
01638 subs.callid.s = (char *) VAL_STRING(&values[r_callid_col]);
01639 subs.callid.len = strlen(subs.callid.s);
01640 subs.to_tag.s = (char *) VAL_STRING(&values[r_to_tag_col]);
01641 subs.to_tag.len = strlen(subs.to_tag.s);
01642 subs.from_tag.s = (char *) VAL_STRING(&values[r_from_tag_col]);
01643 subs.from_tag.len = strlen(subs.from_tag.s);
01644
01645 set_updated(&subs);
01646 }
01647 } while (db_fetch_next(&pa_dbf, pres_fetch_rows, pa_db, &result) == 1
01648 && RES_ROW_N(result) > 0);
01649
01650 error:
01651 if (result) pa_dbf.free_result(pa_db, result);
01652 }
01653
01654 void update_db_subs_timer_dbonly(void)
01655 {
01656 db_op_t qops[1];
01657 db_key_t qcols[1];
01658 db_val_t qvals[1];
01659 db_key_t result_cols[18];
01660 int pres_uri_col, to_user_col, to_domain_col, from_user_col, from_domain_col,
01661 callid_col, totag_col, fromtag_col, event_col, event_id_col,
01662 local_cseq_col, expires_col, rr_col, sockinfo_col,
01663 contact_col, lcontact_col, watcher_user_col, watcher_domain_col;
01664 int n_result_cols = 0;
01665 db1_res_t *result= NULL;
01666 db_row_t *row = NULL;
01667 db_val_t *row_vals= NULL;
01668 int i;
01669 subs_t s, *s_new, *s_array = NULL, *s_del;
01670 str ev_name;
01671 pres_ev_t* event;
01672
01673 LM_DBG("update_db_subs_timer_dbonly: start\n");
01674
01675 qcols[0]= &str_expires_col;
01676 qvals[0].type = DB1_INT;
01677 qvals[0].nul = 0;
01678 qvals[0].val.int_val= (int)time(NULL) - expires_offset;
01679 qops[0]= OP_LT;
01680
01681
01682 result_cols[pres_uri_col=n_result_cols++] =&str_presentity_uri_col;
01683 result_cols[expires_col=n_result_cols++] =&str_expires_col;
01684 result_cols[event_col=n_result_cols++] =&str_event_col;
01685 result_cols[event_id_col=n_result_cols++] =&str_event_id_col;
01686 result_cols[to_user_col=n_result_cols++] =&str_to_user_col;
01687 result_cols[to_domain_col=n_result_cols++] =&str_to_domain_col;
01688 result_cols[from_user_col=n_result_cols++] =&str_from_user_col;
01689 result_cols[from_domain_col=n_result_cols++]=&str_from_domain_col;
01690 result_cols[watcher_user_col=n_result_cols++] =&str_watcher_username_col;
01691 result_cols[watcher_domain_col=n_result_cols++]=&str_watcher_domain_col;
01692 result_cols[callid_col=n_result_cols++] =&str_callid_col;
01693 result_cols[totag_col=n_result_cols++] =&str_to_tag_col;
01694 result_cols[fromtag_col=n_result_cols++] =&str_from_tag_col;
01695 result_cols[local_cseq_col= n_result_cols++]=&str_local_cseq_col;
01696 result_cols[rr_col= n_result_cols++] =&str_record_route_col;
01697 result_cols[sockinfo_col= n_result_cols++] =&str_socket_info_col;
01698 result_cols[contact_col= n_result_cols++] =&str_contact_col;
01699 result_cols[lcontact_col= n_result_cols++] =&str_local_contact_col;
01700
01701 if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
01702 {
01703 LM_ERR("sql use table failed\n");
01704 return;
01705 }
01706
01707 if (pa_dbf.query(pa_db, qcols, qops, qvals, result_cols,
01708 1, n_result_cols, 0, &result) < 0) {
01709 LM_ERR("failed to query database for expired subscriptions\n");
01710 if(result)
01711 pa_dbf.free_result(pa_db, result);
01712 return;
01713 }
01714
01715 if(result== NULL)
01716 return;
01717
01718 if(result->n <=0 ) {
01719 pa_dbf.free_result(pa_db, result);
01720 return;
01721 }
01722 LM_DBG("found %d dialogs\n", result->n);
01723
01724 for(i=0; i<result->n; i++)
01725 {
01726 row = &result->rows[i];
01727 row_vals = ROW_VALUES(row);
01728
01729 memset(&s, 0, sizeof(subs_t));
01730
01731 s.pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
01732 s.pres_uri.len = strlen(s.pres_uri.s);
01733
01734 s.to_user.s= (char*)row_vals[to_user_col].val.string_val;
01735 s.to_user.len= strlen(s.to_user.s);
01736
01737 s.to_domain.s= (char*)row_vals[to_domain_col].val.string_val;
01738 s.to_domain.len= strlen(s.to_domain.s);
01739
01740 s.from_user.s= (char*)row_vals[from_user_col].val.string_val;
01741 s.from_user.len= strlen(s.from_user.s);
01742
01743 s.from_domain.s= (char*)row_vals[from_domain_col].val.string_val;
01744 s.from_domain.len= strlen(s.from_domain.s);
01745
01746 s.watcher_user.s= (char*)row_vals[watcher_user_col].val.string_val;
01747 s.watcher_user.len= strlen(s.watcher_user.s);
01748
01749 s.watcher_domain.s= (char*)row_vals[watcher_domain_col].val.string_val;
01750 s.watcher_domain.len= strlen(s.watcher_domain.s);
01751
01752 s.event_id.s=(char*)row_vals[event_id_col].val.string_val;
01753 s.event_id.len= (s.event_id.s)?strlen(s.event_id.s):0;
01754
01755 s.to_tag.s= (char*)row_vals[totag_col].val.string_val;
01756 s.to_tag.len= strlen(s.to_tag.s);
01757
01758 s.from_tag.s= (char*)row_vals[fromtag_col].val.string_val;
01759 s.from_tag.len= strlen(s.from_tag.s);
01760
01761 s.callid.s= (char*)row_vals[callid_col].val.string_val;
01762 s.callid.len= strlen(s.callid.s);
01763
01764 s.record_route.s= (char*)row_vals[rr_col].val.string_val;
01765 s.record_route.len= (s.record_route.s)?strlen(s.record_route.s):0;
01766
01767 s.contact.s= (char*)row_vals[contact_col].val.string_val;
01768 s.contact.len= strlen(s.contact.s);
01769
01770 s.sockinfo_str.s = (char*)row_vals[sockinfo_col].val.string_val;
01771 s.sockinfo_str.len = s.sockinfo_str.s?strlen(s.sockinfo_str.s):0;
01772
01773 s.local_contact.s = (char*)row_vals[lcontact_col].val.string_val;
01774 s.local_contact.len = s.local_contact.s?strlen(s.local_contact.s):0;
01775
01776 ev_name.s= (char*)row_vals[event_col].val.string_val;
01777 ev_name.len= strlen(ev_name.s);
01778
01779 event= contains_event(&ev_name, 0);
01780 if(event== NULL) {
01781 LM_ERR("Wrong event in database %.*s\n", ev_name.len, ev_name.s);
01782 continue;
01783 }
01784 s.event= event;
01785
01786 s.local_cseq = row_vals[local_cseq_col].val.int_val +1;
01787 s.expires = 0;
01788
01789 s_new= mem_copy_subs(&s, PKG_MEM_TYPE);
01790 if(s_new== NULL)
01791 {
01792 LM_ERR("while copying subs_t structure\n");
01793 continue;
01794 }
01795 s_new->next= s_array;
01796 s_array= s_new;
01797 printf_subs(s_new);
01798 }
01799 pa_dbf.free_result(pa_db, result);
01800
01801 s_new = s_array;
01802 while(s_new) {
01803 handle_expired_subs(s_new);
01804 s_del = s_new;
01805 s_new = s_new->next;
01806 pkg_free(s_del);
01807 }
01808
01809
01810 if(pa_dbf.delete(pa_db, qcols, qops, qvals, 1) < 0)
01811 {
01812 LM_ERR("deleting expired information from database\n");
01813 }
01814 }
01815
01816 void update_db_subs_timer_dbnone(int no_lock)
01817 {
01818 int i;
01819 int now = (int)time(NULL);
01820 subs_t* s= NULL, *prev_s= NULL, *del_s;
01821
01822 LM_DBG("update_db_subs_timer_dbnone: start\n");
01823
01824 for(i=0; i<shtable_size; i++) {
01825 if(!no_lock)
01826 lock_get(&subs_htable[i].lock);
01827
01828 prev_s= subs_htable[i].entries;
01829 s= prev_s->next;
01830
01831 while(s) {
01832 printf_subs(s);
01833 if(s->expires < now - expires_offset) {
01834 LM_DBG("Found expired record\n");
01835 if(!no_lock) {
01836 if(handle_expired_subs(s)< 0) {
01837 LM_ERR("in function handle_expired_record\n");
01838 }
01839 }
01840 del_s= s;
01841 s= s->next;
01842 prev_s->next= s;
01843
01844 if (del_s->contact.s)
01845 shm_free(del_s->contact.s);
01846 shm_free(del_s);
01847 continue;
01848 }
01849 prev_s= s;
01850 s= s->next;
01851 }
01852 if(!no_lock)
01853 lock_release(&subs_htable[i].lock);
01854 }
01855 }
01856
01857
01858
01859 void update_db_subs_timer(db1_con_t *db,db_func_t dbf, shtable_t hash_table,
01860 int htable_size, int no_lock, handle_expired_func_t handle_expired_func)
01861 {
01862 db_key_t query_cols[24], update_cols[6];
01863 db_val_t query_vals[24], update_vals[6];
01864 db_op_t update_ops[1];
01865 subs_t* del_s;
01866 int pres_uri_col, to_user_col, to_domain_col, from_user_col, from_domain_col,
01867 callid_col, totag_col, fromtag_col, event_col,status_col, event_id_col,
01868 local_cseq_col, remote_cseq_col, expires_col, record_route_col,
01869 contact_col, local_contact_col, version_col,socket_info_col,reason_col,
01870 watcher_user_col, watcher_domain_col, updated_col, updated_winfo_col;
01871 int u_expires_col, u_local_cseq_col, u_remote_cseq_col, u_version_col,
01872 u_reason_col, u_status_col;
01873 int i;
01874 subs_t* s= NULL, *prev_s= NULL;
01875 int n_query_cols= 0, n_update_cols= 0;
01876 int n_query_update;
01877 int now = (int)time(NULL);
01878
01879 LM_DBG("update_db_subs_timer: start\n");
01880
01881 query_cols[pres_uri_col= n_query_cols] =&str_presentity_uri_col;
01882 query_vals[pres_uri_col].type = DB1_STR;
01883 query_vals[pres_uri_col].nul = 0;
01884 n_query_cols++;
01885
01886 query_cols[callid_col= n_query_cols] =&str_callid_col;
01887 query_vals[callid_col].type = DB1_STR;
01888 query_vals[callid_col].nul = 0;
01889 n_query_cols++;
01890
01891 query_cols[totag_col= n_query_cols] =&str_to_tag_col;
01892 query_vals[totag_col].type = DB1_STR;
01893 query_vals[totag_col].nul = 0;
01894 n_query_cols++;
01895
01896 query_cols[fromtag_col= n_query_cols] =&str_from_tag_col;
01897 query_vals[fromtag_col].type = DB1_STR;
01898 query_vals[fromtag_col].nul = 0;
01899 n_query_cols++;
01900
01901 n_query_update= n_query_cols;
01902
01903 query_cols[to_user_col= n_query_cols] =&str_to_user_col;
01904 query_vals[to_user_col].type = DB1_STR;
01905 query_vals[to_user_col].nul = 0;
01906 n_query_cols++;
01907
01908 query_cols[to_domain_col= n_query_cols] =&str_to_domain_col;
01909 query_vals[to_domain_col].type = DB1_STR;
01910 query_vals[to_domain_col].nul = 0;
01911 n_query_cols++;
01912
01913 query_cols[from_user_col= n_query_cols] =&str_from_user_col;
01914 query_vals[from_user_col].type = DB1_STR;
01915 query_vals[from_user_col].nul = 0;
01916 n_query_cols++;
01917
01918 query_cols[from_domain_col= n_query_cols] =&str_from_domain_col;
01919 query_vals[from_domain_col].type = DB1_STR;
01920 query_vals[from_domain_col].nul = 0;
01921 n_query_cols++;
01922
01923 query_cols[watcher_user_col= n_query_cols] =&str_watcher_username_col;
01924 query_vals[watcher_user_col].type = DB1_STR;
01925 query_vals[watcher_user_col].nul = 0;
01926 n_query_cols++;
01927
01928 query_cols[watcher_domain_col= n_query_cols] =&str_watcher_domain_col;
01929 query_vals[watcher_domain_col].type = DB1_STR;
01930 query_vals[watcher_domain_col].nul = 0;
01931 n_query_cols++;
01932
01933 query_cols[event_col= n_query_cols] =&str_event_col;
01934 query_vals[event_col].type = DB1_STR;
01935 query_vals[event_col].nul = 0;
01936 n_query_cols++;
01937
01938 query_cols[event_id_col= n_query_cols] =&str_event_id_col;
01939 query_vals[event_id_col].type = DB1_STR;
01940 query_vals[event_id_col].nul = 0;
01941 n_query_cols++;
01942
01943 query_cols[local_cseq_col= n_query_cols]=&str_local_cseq_col;
01944 query_vals[local_cseq_col].type = DB1_INT;
01945 query_vals[local_cseq_col].nul = 0;
01946 n_query_cols++;
01947
01948 query_cols[remote_cseq_col= n_query_cols]=&str_remote_cseq_col;
01949 query_vals[remote_cseq_col].type = DB1_INT;
01950 query_vals[remote_cseq_col].nul = 0;
01951 n_query_cols++;
01952
01953 query_cols[expires_col= n_query_cols] =&str_expires_col;
01954 query_vals[expires_col].type = DB1_INT;
01955 query_vals[expires_col].nul = 0;
01956 n_query_cols++;
01957
01958 query_cols[status_col= n_query_cols] =&str_status_col;
01959 query_vals[status_col].type = DB1_INT;
01960 query_vals[status_col].nul = 0;
01961 n_query_cols++;
01962
01963 query_cols[reason_col= n_query_cols] =&str_reason_col;
01964 query_vals[reason_col].type = DB1_STR;
01965 query_vals[reason_col].nul = 0;
01966 n_query_cols++;
01967
01968 query_cols[record_route_col= n_query_cols] =&str_record_route_col;
01969 query_vals[record_route_col].type = DB1_STR;
01970 query_vals[record_route_col].nul = 0;
01971 n_query_cols++;
01972
01973 query_cols[contact_col= n_query_cols] =&str_contact_col;
01974 query_vals[contact_col].type = DB1_STR;
01975 query_vals[contact_col].nul = 0;
01976 n_query_cols++;
01977
01978 query_cols[local_contact_col= n_query_cols] =&str_local_contact_col;
01979 query_vals[local_contact_col].type = DB1_STR;
01980 query_vals[local_contact_col].nul = 0;
01981 n_query_cols++;
01982
01983 query_cols[socket_info_col= n_query_cols] =&str_socket_info_col;
01984 query_vals[socket_info_col].type = DB1_STR;
01985 query_vals[socket_info_col].nul = 0;
01986 n_query_cols++;
01987
01988 query_cols[version_col= n_query_cols]=&str_version_col;
01989 query_vals[version_col].type = DB1_INT;
01990 query_vals[version_col].nul = 0;
01991 n_query_cols++;
01992
01993 query_cols[updated_col= n_query_cols]=&str_updated_col;
01994 query_vals[updated_col].type = DB1_INT;
01995 query_vals[updated_col].nul = 0;
01996 n_query_cols++;
01997
01998 query_cols[updated_winfo_col= n_query_cols]=&str_updated_winfo_col;
01999 query_vals[updated_winfo_col].type = DB1_INT;
02000 query_vals[updated_winfo_col].nul = 0;
02001 n_query_cols++;
02002
02003
02004 update_cols[u_expires_col= n_update_cols]= &str_expires_col;
02005 update_vals[u_expires_col].type = DB1_INT;
02006 update_vals[u_expires_col].nul = 0;
02007 n_update_cols++;
02008
02009 update_cols[u_status_col= n_update_cols]= &str_status_col;
02010 update_vals[u_status_col].type = DB1_INT;
02011 update_vals[u_status_col].nul = 0;
02012 n_update_cols++;
02013
02014 update_cols[u_reason_col= n_update_cols]= &str_reason_col;
02015 update_vals[u_reason_col].type = DB1_STR;
02016 update_vals[u_reason_col].nul = 0;
02017 n_update_cols++;
02018
02019 update_cols[u_remote_cseq_col= n_update_cols]= &str_remote_cseq_col;
02020 update_vals[u_remote_cseq_col].type = DB1_INT;
02021 update_vals[u_remote_cseq_col].nul = 0;
02022 n_update_cols++;
02023
02024 update_cols[u_local_cseq_col= n_update_cols]= &str_local_cseq_col;
02025 update_vals[u_local_cseq_col].type = DB1_INT;
02026 update_vals[u_local_cseq_col].nul = 0;
02027 n_update_cols++;
02028
02029 update_cols[u_version_col= n_update_cols]= &str_version_col;
02030 update_vals[u_version_col].type = DB1_INT;
02031 update_vals[u_version_col].nul = 0;
02032 n_update_cols++;
02033
02034 for(i=0; i<htable_size; i++)
02035 {
02036 if(!no_lock)
02037 lock_get(&hash_table[i].lock);
02038
02039 prev_s= hash_table[i].entries;
02040 s= prev_s->next;
02041
02042 while(s)
02043 {
02044 printf_subs(s);
02045 if(s->expires < now- expires_offset)
02046 {
02047 LM_DBG("Found expired record\n");
02048 if(!no_lock)
02049 {
02050 if(handle_expired_func(s)< 0)
02051 LM_ERR("in function handle_expired_record\n");
02052 }
02053 del_s= s;
02054 s= s->next;
02055 prev_s->next= s;
02056
02057
02058 if (del_s->contact.s)
02059 shm_free(del_s->contact.s);
02060 shm_free(del_s);
02061 continue;
02062 }
02063 switch(s->db_flag)
02064 {
02065 case NO_UPDATEDB_FLAG:
02066 case WTHROUGHDB_FLAG:
02067 LM_DBG("%s\n", (s->db_flag==NO_UPDATEDB_FLAG)?
02068 "NO_UPDATEDB_FLAG":"WTHROUGHDB_FLAG");
02069 break;
02070
02071 case UPDATEDB_FLAG:
02072 LM_DBG("UPDATEDB_FLAG\n");
02073
02074 query_vals[pres_uri_col].val.str_val= s->pres_uri;
02075 query_vals[callid_col].val.str_val= s->callid;
02076 query_vals[totag_col].val.str_val= s->to_tag;
02077 query_vals[fromtag_col].val.str_val= s->from_tag;
02078
02079 update_vals[u_expires_col].val.int_val= s->expires;
02080 update_vals[u_local_cseq_col].val.int_val= s->local_cseq;
02081 update_vals[u_remote_cseq_col].val.int_val= s->remote_cseq;
02082 update_vals[u_version_col].val.int_val= s->version;
02083 update_vals[u_status_col].val.int_val= s->status;
02084 update_vals[u_reason_col].val.str_val= s->reason;
02085
02086 if(dbf.update(db, query_cols, 0, query_vals, update_cols,
02087 update_vals, n_query_update, n_update_cols)< 0)
02088 {
02089 LM_ERR("updating in database\n");
02090 } else {
02091 s->db_flag= NO_UPDATEDB_FLAG;
02092 }
02093 break;
02094
02095 case INSERTDB_FLAG:
02096 LM_DBG("INSERTDB_FLAG\n");
02097
02098 query_vals[pres_uri_col].val.str_val= s->pres_uri;
02099 query_vals[callid_col].val.str_val= s->callid;
02100 query_vals[totag_col].val.str_val= s->to_tag;
02101 query_vals[fromtag_col].val.str_val= s->from_tag;
02102 query_vals[to_user_col].val.str_val = s->to_user;
02103 query_vals[to_domain_col].val.str_val = s->to_domain;
02104 query_vals[from_user_col].val.str_val = s->from_user;
02105 query_vals[from_domain_col].val.str_val = s->from_domain;
02106 query_vals[watcher_user_col].val.str_val = s->watcher_user;
02107 query_vals[watcher_domain_col].val.str_val = s->watcher_domain;
02108 query_vals[event_col].val.str_val = s->event->name;
02109 query_vals[event_id_col].val.str_val = s->event_id;
02110 query_vals[local_cseq_col].val.int_val= s->local_cseq;
02111 query_vals[remote_cseq_col].val.int_val= s->remote_cseq;
02112 query_vals[expires_col].val.int_val = s->expires;
02113 query_vals[record_route_col].val.str_val = s->record_route;
02114 query_vals[contact_col].val.str_val = s->contact;
02115 query_vals[local_contact_col].val.str_val = s->local_contact;
02116 query_vals[version_col].val.int_val= s->version;
02117 query_vals[status_col].val.int_val= s->status;
02118 query_vals[reason_col].val.str_val= s->reason;
02119 query_vals[socket_info_col].val.str_val= s->sockinfo_str;
02120 query_vals[updated_col].val.int_val = -1;
02121 query_vals[updated_winfo_col].val.int_val = -1;
02122
02123 if(dbf.insert(db,query_cols,query_vals,n_query_cols )<0)
02124 {
02125 LM_ERR("unsuccessful sql insert\n");
02126 } else {
02127 s->db_flag= NO_UPDATEDB_FLAG;
02128 }
02129 break;
02130 }
02131 prev_s= s;
02132 s= s->next;
02133 }
02134 if(!no_lock)
02135 lock_release(&hash_table[i].lock);
02136 }
02137
02138 update_vals[0].val.int_val= (int)time(NULL) - expires_offset;
02139 update_ops[0]= OP_LT;
02140 if(dbf.delete(db, update_cols, update_ops, update_vals, 1) < 0)
02141 {
02142 LM_ERR("deleting expired information from database\n");
02143 }
02144 }
02145
02153 void timer_db_update(unsigned int ticks,void *param)
02154 {
02155 int no_lock=0;
02156 LM_DBG("db_update timer\n");
02157 if(ticks== 0 && param == NULL)
02158 no_lock= 1;
02159
02160
02161 switch (subs_dbmode) {
02162 case DB_ONLY:
02163 if (pres_notifier_processes > 0)
02164 update_db_subs_timer_notifier();
02165 else
02166 update_db_subs_timer_dbonly();
02167 break;
02168 case NO_DB:
02169 update_db_subs_timer_dbnone(no_lock);
02170 break;
02171 default:
02172 if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
02173 {
02174 LM_ERR("sql use table failed\n");
02175 return;
02176 }
02177 update_db_subs_timer(pa_db, pa_dbf, subs_htable, shtable_size,
02178 no_lock, handle_expired_subs);
02179 }
02180 }
02181
02182
02183 int restore_db_subs(void)
02184 {
02185 db_key_t result_cols[22];
02186 db1_res_t *result= NULL;
02187 db_row_t *rows = NULL;
02188 db_val_t *row_vals= NULL;
02189 int i;
02190 int n_result_cols= 0;
02191 int pres_uri_col, expires_col, from_user_col, from_domain_col,to_user_col;
02192 int callid_col,totag_col,fromtag_col,to_domain_col,sockinfo_col,reason_col;
02193 int event_col,contact_col,record_route_col, event_id_col, status_col;
02194 int remote_cseq_col, local_cseq_col, local_contact_col, version_col;
02195 int watcher_user_col, watcher_domain_col;
02196 subs_t s;
02197 str ev_sname;
02198 pres_ev_t* event= NULL;
02199 event_t parsed_event;
02200 unsigned int expires;
02201 unsigned int hash_code;
02202 int nr_rows;
02203
02204 result_cols[pres_uri_col=n_result_cols++] =&str_presentity_uri_col;
02205 result_cols[expires_col=n_result_cols++] =&str_expires_col;
02206 result_cols[event_col=n_result_cols++] =&str_event_col;
02207 result_cols[event_id_col=n_result_cols++] =&str_event_id_col;
02208 result_cols[to_user_col=n_result_cols++] =&str_to_user_col;
02209 result_cols[to_domain_col=n_result_cols++] =&str_to_domain_col;
02210 result_cols[from_user_col=n_result_cols++] =&str_from_user_col;
02211 result_cols[from_domain_col=n_result_cols++] =&str_from_domain_col;
02212 result_cols[watcher_user_col=n_result_cols++] =&str_watcher_username_col;
02213 result_cols[watcher_domain_col=n_result_cols++] =&str_watcher_domain_col;
02214 result_cols[callid_col=n_result_cols++] =&str_callid_col;
02215 result_cols[totag_col=n_result_cols++] =&str_to_tag_col;
02216 result_cols[fromtag_col=n_result_cols++] =&str_from_tag_col;
02217 result_cols[local_cseq_col= n_result_cols++] =&str_local_cseq_col;
02218 result_cols[remote_cseq_col= n_result_cols++] =&str_remote_cseq_col;
02219 result_cols[record_route_col= n_result_cols++] =&str_record_route_col;
02220 result_cols[sockinfo_col= n_result_cols++] =&str_socket_info_col;
02221 result_cols[contact_col= n_result_cols++] =&str_contact_col;
02222 result_cols[local_contact_col= n_result_cols++] =&str_local_contact_col;
02223 result_cols[version_col= n_result_cols++] =&str_version_col;
02224 result_cols[status_col= n_result_cols++] =&str_status_col;
02225 result_cols[reason_col= n_result_cols++] =&str_reason_col;
02226
02227 if(!pa_db)
02228 {
02229 LM_ERR("null database connection\n");
02230 return -1;
02231 }
02232
02233 if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
02234 {
02235 LM_ERR("in use table\n");
02236 return -1;
02237 }
02238
02239
02240 if (db_fetch_query(&pa_dbf, pres_fetch_rows, pa_db, 0, 0, 0, result_cols,
02241 0, n_result_cols, 0, &result) < 0)
02242 {
02243 LM_ERR("querying presentity\n");
02244 goto error;
02245 }
02246
02247 if (result == NULL)
02248 {
02249 LM_ERR("bad result\n");
02250 goto error;
02251 }
02252
02253 do {
02254 nr_rows = RES_ROW_N(result);
02255 LM_DBG("loading information from database %i records\n", nr_rows);
02256
02257 rows = RES_ROWS(result);
02258
02259
02260 for(i=0; i<nr_rows; i++)
02261 {
02262
02263 row_vals = ROW_VALUES(rows +i);
02264 memset(&s, 0, sizeof(subs_t));
02265
02266 expires= row_vals[expires_col].val.int_val;
02267
02268 if(expires< (int)time(NULL))
02269 continue;
02270
02271 s.pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
02272 s.pres_uri.len= strlen(s.pres_uri.s);
02273
02274 s.to_user.s=(char*)row_vals[to_user_col].val.string_val;
02275 s.to_user.len= strlen(s.to_user.s);
02276
02277 s.to_domain.s=(char*)row_vals[to_domain_col].val.string_val;
02278 s.to_domain.len= strlen(s.to_domain.s);
02279
02280 s.from_user.s=(char*)row_vals[from_user_col].val.string_val;
02281 s.from_user.len= strlen(s.from_user.s);
02282
02283 s.from_domain.s=(char*)row_vals[from_domain_col].val.string_val;
02284 s.from_domain.len= strlen(s.from_domain.s);
02285
02286 s.watcher_user.s=(char*)row_vals[watcher_user_col].val.string_val;
02287 s.watcher_user.len= strlen(s.watcher_user.s);
02288
02289 s.watcher_domain.s=(char*)row_vals[watcher_domain_col].val.string_val;
02290 s.watcher_domain.len= strlen(s.watcher_domain.s);
02291
02292 s.to_tag.s=(char*)row_vals[totag_col].val.string_val;
02293 s.to_tag.len= strlen(s.to_tag.s);
02294
02295 s.from_tag.s=(char*)row_vals[fromtag_col].val.string_val;
02296 s.from_tag.len= strlen(s.from_tag.s);
02297
02298 s.callid.s=(char*)row_vals[callid_col].val.string_val;
02299 s.callid.len= strlen(s.callid.s);
02300
02301 ev_sname.s= (char*)row_vals[event_col].val.string_val;
02302 ev_sname.len= strlen(ev_sname.s);
02303
02304 event= contains_event(&ev_sname, &parsed_event);
02305 if(event== NULL)
02306 {
02307 LM_DBG("insert a new event structure in the list waiting"
02308 " to be filled in\n");
02309
02310
02311 event= (pres_ev_t*)shm_malloc(sizeof(pres_ev_t));
02312 if(event== NULL)
02313 {
02314 free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
02315 ERR_MEM(SHM_MEM_STR);
02316 }
02317 memset(event, 0, sizeof(pres_ev_t));
02318 event->name.s= (char*)shm_malloc(ev_sname.len* sizeof(char));
02319 if(event->name.s== NULL)
02320 {
02321 free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
02322 ERR_MEM(SHM_MEM_STR);
02323 }
02324 memcpy(event->name.s,ev_sname.s, ev_sname.len);
02325 event->name.len= ev_sname.len;
02326
02327 event->evp= shm_copy_event(&parsed_event);
02328 if(event->evp== NULL)
02329 {
02330 LM_ERR("ERROR copying event_t structure\n");
02331 free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
02332 goto error;
02333 }
02334 event->next= EvList->events;
02335 EvList->events= event;
02336 }
02337
02338 free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
02339
02340 s.event= event;
02341
02342 s.event_id.s=(char*)row_vals[event_id_col].val.string_val;
02343 if(s.event_id.s)
02344 s.event_id.len= strlen(s.event_id.s);
02345
02346 s.remote_cseq= row_vals[remote_cseq_col].val.int_val;
02347 s.local_cseq= row_vals[local_cseq_col].val.int_val;
02348 s.version= row_vals[version_col].val.int_val;
02349
02350 s.expires= expires- (int)time(NULL);
02351 s.status= row_vals[status_col].val.int_val;
02352
02353 s.reason.s= (char*)row_vals[reason_col].val.string_val;
02354 if(s.reason.s)
02355 s.reason.len= strlen(s.reason.s);
02356
02357 s.contact.s=(char*)row_vals[contact_col].val.string_val;
02358 s.contact.len= strlen(s.contact.s);
02359
02360 s.local_contact.s=(char*)row_vals[local_contact_col].val.string_val;
02361 s.local_contact.len= strlen(s.local_contact.s);
02362
02363 s.record_route.s=(char*)row_vals[record_route_col].val.string_val;
02364 if(s.record_route.s)
02365 s.record_route.len= strlen(s.record_route.s);
02366
02367 s.sockinfo_str.s=(char*)row_vals[sockinfo_col].val.string_val;
02368 s.sockinfo_str.len= strlen(s.sockinfo_str.s);
02369 s.db_flag = (subs_dbmode==WRITE_THROUGH)?WTHROUGHDB_FLAG:NO_UPDATEDB_FLAG;
02370 hash_code= core_hash(&s.pres_uri, &s.event->name, shtable_size);
02371 if(insert_shtable(subs_htable, hash_code, &s)< 0)
02372 {
02373 LM_ERR("adding new record in hash table\n");
02374 goto error;
02375 }
02376 }
02377
02378 } while((db_fetch_next(&pa_dbf, pres_fetch_rows, pa_db, &result)==1)
02379 && (RES_ROW_N(result)>0));
02380
02381 pa_dbf.free_result(pa_db, result);
02382
02383
02384 if(subs_dbmode == NO_DB) {
02385 if(pa_dbf.delete(pa_db, 0,0,0,0)< 0)
02386 {
02387 LM_ERR("deleting all records from database table\n");
02388 return -1;
02389 }
02390 }
02391 return 0;
02392
02393 error:
02394 if(result)
02395 pa_dbf.free_result(pa_db, result);
02396 return -1;
02397
02398 }
02399
02400 int get_db_subs_auth(subs_t* subs, int* found)
02401 {
02402 db_key_t db_keys[5];
02403 db_val_t db_vals[5];
02404 int n_query_cols= 0;
02405 db_key_t result_cols[3];
02406 db1_res_t *result = NULL;
02407 db_row_t *row ;
02408 db_val_t *row_vals ;
02409
02410 db_keys[n_query_cols] =&str_presentity_uri_col;
02411 db_vals[n_query_cols].type = DB1_STR;
02412 db_vals[n_query_cols].nul = 0;
02413 db_vals[n_query_cols].val.str_val= subs->pres_uri;
02414 n_query_cols++;
02415
02416 db_keys[n_query_cols] =&str_watcher_username_col;
02417 db_vals[n_query_cols].type = DB1_STR;
02418 db_vals[n_query_cols].nul = 0;
02419 db_vals[n_query_cols].val.str_val = subs->watcher_user;
02420 n_query_cols++;
02421
02422 db_keys[n_query_cols] =&str_watcher_domain_col;
02423 db_vals[n_query_cols].type = DB1_STR;
02424 db_vals[n_query_cols].nul = 0;
02425 db_vals[n_query_cols].val.str_val = subs->watcher_domain;
02426 n_query_cols++;
02427
02428 db_keys[n_query_cols] =&str_event_col;
02429 db_vals[n_query_cols].type = DB1_STR;
02430 db_vals[n_query_cols].nul = 0;
02431 db_vals[n_query_cols].val.str_val = subs->event->name;
02432 n_query_cols++;
02433
02434 result_cols[0] = &str_status_col;
02435 result_cols[1] = &str_reason_col;
02436
02437 if(pa_dbf.use_table(pa_db, &watchers_table)< 0)
02438 {
02439 LM_ERR("in use table\n");
02440 return -1;
02441 }
02442
02443 if(pa_dbf.query(pa_db, db_keys, 0, db_vals, result_cols,
02444 n_query_cols, 2, 0, &result )< 0)
02445 {
02446 LM_ERR("while querying watchers table\n");
02447 if(result)
02448 pa_dbf.free_result(pa_db, result);
02449 return -1;
02450 }
02451 if(result== NULL)
02452 return -1;
02453
02454 if(result->n<= 0)
02455 {
02456 *found= 0;
02457 pa_dbf.free_result(pa_db, result);
02458 return 0;
02459 }
02460
02461 *found= 1;
02462 row = &result->rows[0];
02463 row_vals = ROW_VALUES(row);
02464 subs->status= row_vals[0].val.int_val;
02465
02466 if(row_vals[1].val.string_val)
02467 {
02468
02469 subs->reason.len= strlen(row_vals[1].val.string_val);
02470 if(subs->reason.len== 0)
02471 subs->reason.s= NULL;
02472 else
02473 {
02474 subs->reason.s= (char*)pkg_malloc(subs->reason.len*sizeof(char));
02475 if(subs->reason.s== NULL)
02476 {
02477 pa_dbf.free_result(pa_db, result);
02478 ERR_MEM(PKG_MEM_STR);
02479 }
02480 memcpy(subs->reason.s, row_vals[1].val.string_val, subs->reason.len);
02481 }
02482 }
02483
02484 pa_dbf.free_result(pa_db, result);
02485 return 0;
02486 error:
02487 return -1;
02488 }
02489
02490 int insert_db_subs_auth(subs_t* subs)
02491 {
02492 db_key_t db_keys[10];
02493 db_val_t db_vals[10];
02494 int n_query_cols= 0;
02495
02496 db_keys[n_query_cols] =&str_presentity_uri_col;
02497 db_vals[n_query_cols].type = DB1_STR;
02498 db_vals[n_query_cols].nul = 0;
02499 db_vals[n_query_cols].val.str_val= subs->pres_uri;
02500 n_query_cols++;
02501
02502 db_keys[n_query_cols] =&str_watcher_username_col;
02503 db_vals[n_query_cols].type = DB1_STR;
02504 db_vals[n_query_cols].nul = 0;
02505 db_vals[n_query_cols].val.str_val = subs->watcher_user;
02506 n_query_cols++;
02507
02508 db_keys[n_query_cols] =&str_watcher_domain_col;
02509 db_vals[n_query_cols].type = DB1_STR;
02510 db_vals[n_query_cols].nul = 0;
02511 db_vals[n_query_cols].val.str_val = subs->watcher_domain;
02512 n_query_cols++;
02513
02514 db_keys[n_query_cols] =&str_event_col;
02515 db_vals[n_query_cols].type = DB1_STR;
02516 db_vals[n_query_cols].nul = 0;
02517 db_vals[n_query_cols].val.str_val = subs->event->name;
02518 n_query_cols++;
02519
02520 db_keys[n_query_cols] =&str_status_col;
02521 db_vals[n_query_cols].type = DB1_INT;
02522 db_vals[n_query_cols].nul = 0;
02523 db_vals[n_query_cols].val.int_val = subs->status;
02524 n_query_cols++;
02525
02526 db_keys[n_query_cols] = &str_inserted_time_col;
02527 db_vals[n_query_cols].type = DB1_INT;
02528 db_vals[n_query_cols].nul = 0;
02529 db_vals[n_query_cols].val.int_val= (int)time(NULL);
02530 n_query_cols++;
02531
02532 db_keys[n_query_cols] =&str_reason_col;
02533 db_vals[n_query_cols].type = DB1_STR;
02534 db_vals[n_query_cols].nul = 0;
02535 if(subs->reason.s && subs->reason.len)
02536 db_vals[n_query_cols].val.str_val = subs->reason;
02537 else
02538 {
02539 db_vals[n_query_cols].val.str_val.s = "";
02540 db_vals[n_query_cols].val.str_val.len = 0;
02541 }
02542 n_query_cols++;
02543
02544 if (pa_dbf.use_table(pa_db, &watchers_table) < 0)
02545 {
02546 LM_ERR("in use_table\n");
02547 return -1;
02548 }
02549
02550 if (pa_dbf.replace != NULL)
02551 {
02552 if(pa_dbf.replace(pa_db, db_keys, db_vals, n_query_cols,
02553 2, 0) < 0)
02554 {
02555 LM_ERR("in sql replace\n");
02556 return -1;
02557 }
02558 }
02559 else
02560 {
02561
02562
02563
02564
02565
02566
02567 if(pa_dbf.insert(pa_db, db_keys, db_vals, n_query_cols )< 0)
02568 {
02569 LM_ERR("in sql insert\n");
02570 return -1;
02571 }
02572 }
02573
02574 return 0;
02575 }