modules_k/presence/subscribe.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * presence module - presence server implementation
00005  *
00006  * Copyright (C) 2006 Voice Sistem S.R.L.
00007  *
00008  * This file is part of openser, a free SIP serves.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  * History:
00025  * --------
00026  *  2006-08-15  initial version (Anca Vamanu)
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         /* delete record from hash table also if not in dbonly mode */
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         /* Set the notifier/update fields for the subscription */
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) /*if a SUBSCRIBE within a dialog */
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 /* if unsubscribe for winfo */
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                 /* if subscriptions are stored in memory, update them */
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                 /* for modes that update the subscription synchronously in database, write in db */
00601                 if(subs_dbmode == DB_ONLY ||  subs_dbmode== WRITE_THROUGH)
00602                 {
00603                         /* update in database table */
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                         /* TODO if req_auth, the subscription was in the watcher table first, we must delete it */
00639                 }
00640                 /*otherwise there is a subscription outside a dialog with expires= 0 
00641                  * no update in database, but should try to send Notify */
00642                 else
00643                 {
00644                         LM_DBG("subscription request with expiry=0 not in dialog\n");
00645                 }
00646         }
00647 
00648         /* reply_and_notify  */
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         /* ??? rename to avoid collisions with other symbols */
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         /* inspecting the Event header field */
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         /* search event in the list */
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         /* extract the id if any*/
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         /* getting presentity uri from Request-URI if initial subscribe - or else from database*/
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         /* mark that the received event is a SUBSCRIBE message */
00881         subs.recv_event = PRES_SUBSCRIBE_RECV;
00882 
00883         /* call event specific subscription handling */
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         /* if dialog initiation Subscribe - get subscription state */
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                         /* query in watchers_table */
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                                 /*default 'pending' status */
00913                                 subs.status= PENDING_STATUS;
00914                                 subs.reason.s= NULL;
00915                                 subs.reason.len= 0;
00916                                 /* here a query to xcap server must be done -> new process maybe */
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         /* check if correct status */
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         /* examine the expire header field */
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         /* examine the to header */
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         /* examine the from header */
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                 /* parsing from header */
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         /* get to_tag if the message does not have a to_tag*/
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                 /* user_contact@from_domain */
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         /*process record route and add it to a string*/
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                 //      goto error;
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         /* first try to_user== pres_user and to_domain== pres_domain */
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         /* take one row at a time */
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         /* send Notify with state=terminated;reason=timeout */
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         /* query the expired subscriptions */
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         /* delete the expired subscriptions */
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         /* cols and values used for update */
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                                 /* need for a struct free/destroy? */
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                         } /* switch */
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         /* select the whole table and all the columns */
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                 /* for every row */
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                                 /*insert a new event structure in the list waiting to be filled in*/
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         /* delete all records  only if in memory mode */
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                 /* If you use insert() instead of replace() be prepared for some
02562                    DB error messages.  There is a lot of time between the 
02563                    query() that indicated there was no matching entry in the DB
02564                    and this insert(), so on a multi-user system it is entirely
02565                    possible (even likely) that a record will be added after the
02566                    query() but before this insert(). */
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 }