presence/subscribe.c

Go to the documentation of this file.
00001 /*
00002  * $Id: subscribe.c 5674 2009-03-08 18:35:20Z miconda $
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)
00027  */
00028 
00029 /*! \file
00030  * \brief Kamailio presence module :: Support for SUBSCRIBE handling
00031  * \ingroup presence 
00032  */
00033 
00034 
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 "presence.h"
00042 #include "subscribe.h"
00043 #include "utils_func.h"
00044 #include "notify.h"
00045 #include "../pua/hash.h"
00046 
00047 int get_stored_info(struct sip_msg* msg, subs_t* subs, int* error_ret,
00048       str* reply_str);
00049 int get_database_info(struct sip_msg* msg, subs_t* subs, int* error_ret,
00050       str* reply_str);
00051 int get_db_subs_auth(subs_t* subs, int* found);
00052 int insert_db_subs_auth(subs_t* subs);
00053 
00054 static str su_200_rpl  = str_init("OK");
00055 static str pu_481_rpl  = str_init("Subscription does not exist");
00056 static str pu_400_rpl  = str_init("Bad request");
00057 static str pu_500_rpl  = str_init("Server Internal Error");
00058 static str pu_489_rpl  = str_init("Bad Event");
00059 
00060 
00061 int send_2XX_reply(struct sip_msg * msg, int reply_code, int lexpire,
00062       str* local_contact)
00063 {
00064    str hdr_append = {0, 0};
00065    str tmp;
00066    char *t = NULL;
00067    
00068    tmp.s = int2str((unsigned long)lexpire, &tmp.len);
00069    hdr_append.len = 9 + tmp.len + CRLF_LEN
00070       + 10 + local_contact->len + 16 + CRLF_LEN;
00071    hdr_append.s = (char *)pkg_malloc(sizeof(char)*(hdr_append.len+1));
00072    if(hdr_append.s == NULL)
00073    {
00074       ERR_MEM(PKG_MEM_STR);
00075    }
00076    strncpy(hdr_append.s, "Expires: ", 9);
00077    strncpy(hdr_append.s+9, tmp.s, tmp.len);
00078    tmp.s = hdr_append.s+9+tmp.len;
00079    strncpy(tmp.s, CRLF, CRLF_LEN);
00080    tmp.s += CRLF_LEN;
00081    strncpy(tmp.s, "Contact: <", 10);
00082    tmp.s += 10;
00083    strncpy(tmp.s, local_contact->s, local_contact->len);
00084    tmp.s[local_contact->len] = '\0';
00085    t = strstr(tmp.s, ";transport=");
00086    tmp.s += local_contact->len;
00087    if(t==NULL)
00088    {
00089       switch (msg->rcv.proto)
00090       {
00091          case PROTO_TCP:
00092             strncpy(tmp.s, ";transport=tcp", 14);
00093             tmp.s += 14;
00094             hdr_append.len -= 1;
00095          break;
00096          case PROTO_TLS:
00097             strncpy(tmp.s, ";transport=tls", 14);
00098             tmp.s += 14;
00099             hdr_append.len -= 1;
00100          break;
00101          case PROTO_SCTP:
00102             strncpy(tmp.s, ";transport=sctp", 15);
00103             tmp.s += 15;
00104          break;
00105          default:
00106             hdr_append.len -= 15;
00107       }
00108    } else {
00109       hdr_append.len -= 15;
00110    }
00111    *tmp.s = '>';
00112    strncpy(tmp.s+1, CRLF, CRLF_LEN);
00113 
00114    hdr_append.s[hdr_append.len]= '\0';
00115    
00116    if (add_lump_rpl( msg, hdr_append.s, hdr_append.len, LUMP_RPL_HDR)==0 )
00117    {
00118       LM_ERR("unable to add lump_rl\n");
00119       goto error;
00120    }
00121 
00122    if( slb.send_reply(msg, reply_code, &su_200_rpl)== -1)
00123    {
00124       LM_ERR("sending reply\n");
00125       goto error;
00126    }
00127    
00128    pkg_free(hdr_append.s);
00129    return 0;
00130 
00131 error:
00132 
00133    if(hdr_append.s!=NULL)
00134       pkg_free(hdr_append.s);
00135    return -1;
00136 }
00137 
00138 
00139 int delete_db_subs(str pres_uri, str ev_stored_name, str to_tag)
00140 {
00141    db_key_t query_cols[5];
00142    db_val_t query_vals[5];
00143    int n_query_cols= 0;
00144 
00145    query_cols[n_query_cols] = &str_presentity_uri_col;
00146    query_vals[n_query_cols].type = DB_STR;
00147    query_vals[n_query_cols].nul = 0;
00148    query_vals[n_query_cols].val.str_val = pres_uri;
00149    n_query_cols++;
00150 
00151    query_cols[n_query_cols] = &str_event_col;
00152    query_vals[n_query_cols].type = DB_STR;
00153    query_vals[n_query_cols].nul = 0;
00154    query_vals[n_query_cols].val.str_val = ev_stored_name;
00155    n_query_cols++;
00156 
00157    query_cols[n_query_cols] = &str_to_tag_col;
00158    query_vals[n_query_cols].type = DB_STR;
00159    query_vals[n_query_cols].nul = 0;
00160    query_vals[n_query_cols].val.str_val = to_tag;
00161    n_query_cols++;
00162    
00163    if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0) 
00164    {
00165       LM_ERR("in use table sql operation\n");
00166       return -1;
00167    }
00168 
00169    if(pa_dbf.delete(pa_db, query_cols, 0, query_vals,
00170             n_query_cols)< 0 )
00171    {
00172       LM_ERR("sql delete failed\n");
00173       return -1;
00174    }
00175 
00176    return 0;
00177 }
00178 
00179 int update_subs_db(subs_t* subs, int type)
00180 {
00181    db_key_t query_cols[22], update_keys[7];
00182    db_val_t query_vals[22], update_vals[7];
00183    int n_update_cols= 0;
00184    int n_query_cols = 0;
00185 
00186    query_cols[n_query_cols] = &str_presentity_uri_col;
00187    query_vals[n_query_cols].type = DB_STR;
00188    query_vals[n_query_cols].nul = 0;
00189    query_vals[n_query_cols].val.str_val = subs->pres_uri;
00190    n_query_cols++;
00191    
00192    query_cols[n_query_cols] = &str_watcher_username_col;
00193    query_vals[n_query_cols].type = DB_STR;
00194    query_vals[n_query_cols].nul = 0;
00195    query_vals[n_query_cols].val.str_val = subs->from_user;
00196    n_query_cols++;
00197    
00198    query_cols[n_query_cols] = &str_watcher_domain_col;
00199    query_vals[n_query_cols].type = DB_STR;
00200    query_vals[n_query_cols].nul = 0;
00201    query_vals[n_query_cols].val.str_val = subs->from_domain;
00202    n_query_cols++;
00203 
00204    query_cols[n_query_cols] = &str_event_col;
00205    query_vals[n_query_cols].type = DB_STR;
00206    query_vals[n_query_cols].nul = 0;
00207    query_vals[n_query_cols].val.str_val = subs->event->name;
00208    n_query_cols++;
00209 
00210    if(subs->event_id.s)
00211    {
00212       query_cols[n_query_cols] = &str_event_id_col;
00213       query_vals[n_query_cols].type = DB_STR;
00214       query_vals[n_query_cols].nul = 0;
00215       query_vals[n_query_cols].val.str_val = subs->event_id;
00216       n_query_cols++;
00217    }
00218    query_cols[n_query_cols] = &str_callid_col;
00219    query_vals[n_query_cols].type = DB_STR;
00220    query_vals[n_query_cols].nul = 0;
00221    query_vals[n_query_cols].val.str_val = subs->callid;
00222    n_query_cols++;
00223 
00224    query_cols[n_query_cols] = &str_to_tag_col;
00225    query_vals[n_query_cols].type = DB_STR;
00226    query_vals[n_query_cols].nul = 0;
00227    query_vals[n_query_cols].val.str_val = subs->to_tag;
00228    n_query_cols++;
00229 
00230    query_cols[n_query_cols] = &str_from_tag_col;
00231    query_vals[n_query_cols].type = DB_STR;
00232    query_vals[n_query_cols].nul = 0;
00233    query_vals[n_query_cols].val.str_val = subs->from_tag;
00234    n_query_cols++;
00235 
00236    if(type & REMOTE_TYPE)
00237    {
00238       update_keys[n_update_cols] = &str_expires_col;
00239       update_vals[n_update_cols].type = DB_INT;
00240       update_vals[n_update_cols].nul = 0;
00241       update_vals[n_update_cols].val.int_val = subs->expires + (int)time(NULL);
00242       n_update_cols++;
00243    
00244       update_keys[n_update_cols] = &str_remote_cseq_col;
00245       update_vals[n_update_cols].type = DB_INT;
00246       update_vals[n_update_cols].nul = 0;
00247       update_vals[n_update_cols].val.int_val = subs->remote_cseq; 
00248       n_update_cols++;
00249    }
00250    else
00251    {  
00252       update_keys[n_update_cols] = &str_local_cseq_col;
00253       update_vals[n_update_cols].type = DB_INT;
00254       update_vals[n_update_cols].nul = 0;
00255       update_vals[n_update_cols].val.int_val = subs->local_cseq+ 1;
00256       n_update_cols++;
00257    
00258       update_keys[n_update_cols] = &str_version_col;
00259       update_vals[n_update_cols].type = DB_INT;
00260       update_vals[n_update_cols].nul = 0;
00261       update_vals[n_update_cols].val.int_val = subs->version+ 1;
00262       n_update_cols++;
00263    }
00264 
00265    update_keys[n_update_cols] = &str_status_col;
00266    update_vals[n_update_cols].type = DB_INT;
00267    update_vals[n_update_cols].nul = 0;
00268    update_vals[n_update_cols].val.int_val = subs->status;
00269    n_update_cols++;
00270 
00271    update_keys[n_update_cols] = &str_reason_col;
00272    update_vals[n_update_cols].type = DB_STR;
00273    update_vals[n_update_cols].nul = 0;
00274    update_vals[n_update_cols].val.str_val = subs->reason;
00275    n_update_cols++;
00276    
00277    if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
00278    {
00279       LM_ERR("in use table sql operation\n");   
00280       return -1;
00281    }
00282       
00283    if( pa_dbf.update( pa_db,query_cols, 0, query_vals,
00284             update_keys, update_vals, n_query_cols,n_update_cols)<0) 
00285    {
00286       LM_ERR("updating presence information\n");
00287       return -1;
00288    }
00289    return 0;
00290 }
00291 
00292 int update_subscription(struct sip_msg* msg, subs_t* subs, int to_tag_gen,
00293       int* sent_reply)
00294 {  
00295    unsigned int hash_code;
00296    
00297    printf_subs(subs);   
00298    
00299    *sent_reply= 0;
00300 
00301    hash_code= core_hash(&subs->pres_uri, &subs->event->name, shtable_size);
00302 
00303    if( to_tag_gen ==0) /*if a SUBSCRIBE within a dialog */
00304    {
00305       if(subs->expires == 0)
00306       {
00307          LM_DBG("expires =0 -> deleting record\n");
00308       
00309          if( delete_db_subs(subs->pres_uri, 
00310                   subs->event->name, subs->to_tag)< 0)
00311          {
00312             LM_ERR("deleting subscription record from database\n");
00313             goto error;
00314          }
00315          /* delete record from hash table also */
00316 
00317          subs->local_cseq= delete_shtable(subs_htable,hash_code,
00318                subs->to_tag);
00319       
00320          if(subs->event->type & PUBL_TYPE)
00321          {  
00322             if( send_2XX_reply(msg, 202, subs->expires,
00323                      &subs->local_contact) <0)
00324             {
00325                LM_ERR("sending 202 OK\n");
00326                goto error;
00327             }
00328             *sent_reply= 1;
00329             if(subs->event->wipeer)
00330             {
00331                if(query_db_notify(&subs->pres_uri,
00332                         subs->event->wipeer, NULL)< 0)
00333                {
00334                   LM_ERR("Could not send notify for winfo\n");
00335                   goto error;
00336                }
00337             }
00338 
00339          }  
00340          else /* if unsubscribe for winfo */
00341          {
00342             if( send_2XX_reply(msg, 200, subs->expires,
00343                      &subs->local_contact) <0)
00344             {
00345                LM_ERR("sending 200 OK reply\n");
00346                goto error;
00347             }
00348             *sent_reply= 1;
00349          }
00350       
00351          if(notify(subs, NULL, NULL, 0)< 0)
00352          {
00353             LM_ERR("Could not send notify\n");
00354             goto error;
00355          }
00356          return 1;
00357       }
00358 
00359       if(update_shtable(subs_htable, hash_code, subs, REMOTE_TYPE)< 0)
00360       {
00361          if(fallback2db)
00362          {
00363             /* update in database table */
00364             if(update_subs_db(subs, REMOTE_TYPE)< 0)
00365             {
00366                LM_ERR("updating subscription in database table\n");
00367                goto error;
00368             }
00369          }
00370          else
00371          {
00372             LM_ERR("updating subscription record in hash table\n");
00373             goto error;
00374          }
00375       }
00376    }
00377    else
00378    {
00379       if(subs->expires!= 0)
00380       {  
00381          if(insert_shtable(subs_htable,hash_code,subs)< 0)
00382          {
00383             LM_ERR("inserting new record in subs_htable\n");
00384             goto error;
00385          }
00386       }
00387       /*otherwise there is a subscription outside a dialog with expires= 0 
00388        * no update in database, but should try to send Notify */
00389    }
00390 
00391 /* reply_and_notify  */
00392 
00393    if(subs->event->type & PUBL_TYPE)
00394    {  
00395       if(send_2XX_reply(msg, 202, subs->expires,
00396                &subs->local_contact)<0)
00397       {
00398          LM_ERR("sending 202 OK reply\n");
00399          goto error;
00400       }
00401       *sent_reply= 1;
00402       
00403       if(subs->expires!= 0 && subs->event->wipeer)
00404       {  
00405          LM_DBG("send Notify with winfo\n");
00406          if(query_db_notify(&subs->pres_uri, subs->event->wipeer, subs)< 0)
00407          {
00408             LM_ERR("Could not send notify winfo\n");
00409             goto error;
00410          }  
00411          if(subs->send_on_cback== 0)
00412          {  
00413             if(notify(subs, NULL, NULL, 0)< 0)
00414             {
00415                LM_ERR("Could not send notify\n");
00416                goto error;
00417             }
00418          }
00419       }
00420       else
00421       {
00422          if(notify(subs, NULL, NULL, 0)< 0)
00423          {
00424             LM_ERR("Could not send notify\n");
00425             goto error;
00426          }
00427       }  
00428          
00429    }
00430    else 
00431    {
00432       if( send_2XX_reply(msg, 200, subs->expires,
00433                &subs->local_contact)<0)
00434       {
00435          LM_ERR("sending 200 OK reply\n");
00436          goto error;
00437       }     
00438       *sent_reply= 1;
00439       
00440       if(notify(subs, NULL, NULL, 0 )< 0)
00441       {
00442          LM_ERR("sending notify request\n");
00443          goto error;
00444       }
00445    }
00446    return 0;
00447    
00448 error:
00449 
00450    LM_ERR("occured\n");
00451    return -1;
00452 
00453 }
00454 
00455 void msg_watchers_clean(unsigned int ticks,void *param)
00456 {
00457    db_key_t db_keys[3], result_cols[1];
00458    db_val_t db_vals[3];
00459    db_op_t  db_ops[3] ;
00460    db_res_t *result= NULL;
00461 
00462    LM_DBG("cleaning pending subscriptions\n");
00463    
00464    db_keys[0] = &str_inserted_time_col;
00465    db_ops[0] = OP_LT;
00466    db_vals[0].type = DB_INT;
00467    db_vals[0].nul = 0;
00468    db_vals[0].val.int_val = (int)time(NULL)- 24*3600 ;
00469 
00470    db_keys[1] = &str_status_col;
00471    db_ops [1] = OP_EQ;
00472    db_vals[1].type = DB_INT;
00473    db_vals[1].nul = 0;
00474    db_vals[1].val.int_val = PENDING_STATUS;
00475    
00476    result_cols[0]= &str_id_col;
00477 
00478    if (pa_dbf.use_table(pa_db, &watchers_table) < 0) 
00479    {
00480       LM_ERR("unsuccessful use table sql operation\n");
00481       return ;
00482    }
00483    
00484    if(pa_dbf.query(pa_db, db_keys, db_ops, db_vals, result_cols, 2, 1, 0, &result )< 0)
00485    {
00486       LM_ERR("querying database for expired messages\n");
00487       if(result)
00488          pa_dbf.free_result(pa_db, result);
00489       return;
00490    }
00491    if(result == NULL)
00492       return;
00493    if(result->n <= 0)
00494    {
00495       pa_dbf.free_result(pa_db, result);
00496       return;
00497    }
00498    pa_dbf.free_result(pa_db, result);
00499 
00500    if (pa_dbf.delete(pa_db, db_keys, db_ops, db_vals, 2) < 0) 
00501       LM_ERR("cleaning pending subscriptions\n");
00502 }
00503 
00504 int handle_subscribe(struct sip_msg* msg, char* str1, char* str2)
00505 {
00506    int  to_tag_gen = 0;
00507    subs_t subs;
00508    pres_ev_t* event= NULL;
00509    event_t* parsed_event= NULL;
00510    param_t* ev_param= NULL;
00511    int found;
00512    str reason= {0, 0};
00513    struct sip_uri uri;
00514    int reply_code;
00515    str reply_str;
00516    int sent_reply= 0;
00517 
00518    /* ??? rename to avoid collisions with other symbols */
00519    counter++;
00520 
00521    memset(&subs, 0, sizeof(subs_t));
00522    
00523    reply_code= 500;
00524    reply_str= pu_500_rpl;
00525 
00526    if( parse_headers(msg,HDR_EOH_F, 0)==-1 )
00527    {
00528       LM_ERR("parsing headers\n");
00529       reply_code= 400;
00530       reply_str= pu_400_rpl;
00531       goto error;
00532    }
00533    
00534    /* inspecting the Event header field */
00535    if(msg->event && msg->event->body.len > 0)
00536    {
00537       if (!msg->event->parsed && (parse_event(msg->event) < 0))
00538       {
00539          reply_code= 400;
00540          reply_str= pu_400_rpl;
00541          goto error;
00542       }
00543       if(((event_t*)msg->event->parsed)->parsed == EVENT_OTHER)
00544       {  
00545          goto bad_event;
00546       }
00547    }
00548    else
00549       goto bad_event;
00550 
00551    /* search event in the list */
00552    parsed_event= (event_t*)msg->event->parsed;
00553    event= search_event(parsed_event);
00554    if(event== NULL)
00555    {
00556       goto bad_event;
00557    }
00558    subs.event= event;
00559    
00560    /* extract the id if any*/
00561    ev_param= parsed_event->params;
00562    while(ev_param)
00563    {
00564       if(ev_param->name.len== 2 && strncmp(ev_param->name.s, "id", 2)== 0)
00565       {
00566          subs.event_id= ev_param->body;
00567          break;
00568       }
00569       ev_param= ev_param->next;
00570    }     
00571    
00572    if(extract_sdialog_info(&subs, msg, max_expires, &to_tag_gen,
00573             server_address)< 0)
00574    {
00575       LM_ERR("failed to extract dialog information\n");
00576       goto error;
00577    }
00578 
00579    /* getting presentity uri from Request-URI if initial subscribe - or else from database*/
00580    if(to_tag_gen)
00581    {
00582       if(parsed_event->parsed!= EVENT_DIALOG_SLA)
00583       {
00584          if( parse_sip_msg_uri(msg)< 0)
00585          {
00586             LM_ERR("failed to parse R-URI\n");
00587             return -1;
00588          }
00589          if(uandd_to_uri(msg->parsed_uri.user, msg->parsed_uri.host,
00590                &subs.pres_uri)< 0)
00591          {
00592             LM_ERR("failed to construct uri from user and domain\n");
00593             goto error;
00594          }
00595       }
00596    }
00597    else
00598    {
00599       if(get_stored_info(msg, &subs, &reply_code, &reply_str )< 0)
00600       {
00601          LM_ERR("getting stored info\n");
00602          goto error;
00603       }
00604       reason= subs.reason;
00605    }  
00606 
00607    /* call event specific subscription handling */
00608    if(event->evs_subs_handl)
00609    {
00610       if(event->evs_subs_handl(msg)< 0)
00611       {
00612          LM_ERR("in event specific subscription handling\n");
00613          goto error;
00614       }
00615    }  
00616 
00617 
00618    /* if dialog initiation Subscribe - get subscription state */
00619    if(to_tag_gen)
00620    {
00621       if(!event->req_auth) 
00622          subs.status = ACTIVE_STATUS;
00623       else   
00624       {
00625          /* query in watchers_table */
00626          if(get_db_subs_auth(&subs, &found)< 0)
00627          {
00628             LM_ERR("getting subscription status from watchers table\n");
00629             goto error;
00630          }
00631          if(found== 0)
00632          {
00633             /*default 'pending' status */
00634             subs.status= PENDING_STATUS;
00635             subs.reason.s= NULL;
00636             subs.reason.len= 0;
00637             /* here a query to xcap server must be done -> new process maybe */
00638          
00639             if(parse_uri(subs.pres_uri.s, subs.pres_uri.len, &uri)< 0)
00640             {
00641                LM_ERR("parsing uri\n");
00642                goto error;
00643 
00644             }
00645             if(subs.event->get_rules_doc(&uri.user, &uri.host, &subs.auth_rules_doc)< 0)
00646             {
00647                LM_ERR("getting rules doc\n");
00648                goto error;
00649             }
00650             
00651             if(subs.event->get_auth_status(&subs)< 0)
00652             {
00653                LM_ERR("in event specific function is_watcher_allowed\n");
00654                goto error;
00655             }
00656             if(get_status_str(subs.status)== NULL)
00657             {
00658                LM_ERR("wrong status= %d\n", subs.status);
00659                goto error;
00660             }
00661 
00662             if(insert_db_subs_auth(&subs)< 0)
00663             {
00664                LM_ERR("while inserting record in watchers table\n");
00665                goto error;
00666             }
00667          }
00668          else
00669          {
00670             reason= subs.reason;
00671          }
00672       }
00673    }
00674 
00675    /* check if correct status */
00676    if(get_status_str(subs.status)== NULL)
00677    {
00678       LM_ERR("wrong status\n");
00679       goto error;
00680    }
00681     LM_DBG("subscription status= %s - %s\n", get_status_str(subs.status), 
00682             found==0?"inserted":"found in watcher table");
00683    
00684    if(update_subscription(msg, &subs, to_tag_gen, &sent_reply) <0)
00685    {  
00686       LM_ERR("in update_subscription\n");
00687       goto error;
00688    }
00689    if(subs.auth_rules_doc)
00690    {
00691       pkg_free(subs.auth_rules_doc->s);
00692       pkg_free(subs.auth_rules_doc);
00693    }
00694    if(reason.s)
00695       pkg_free(reason.s);
00696    
00697    if(subs.pres_uri.s)
00698       pkg_free(subs.pres_uri.s);
00699    
00700    if((!server_address.s) || (server_address.len== 0))
00701    {
00702       pkg_free(subs.local_contact.s);
00703    }
00704    if(subs.record_route.s)
00705       pkg_free(subs.record_route.s);
00706 
00707    return 1;
00708 
00709 bad_event:
00710 
00711    LM_ERR("Missing or unsupported event header field value\n");
00712       
00713    if(parsed_event && parsed_event->text.s)
00714       LM_ERR("\tevent= %.*s\n",parsed_event->text.len,parsed_event->text.s);
00715    
00716    reply_code= BAD_EVENT_CODE;
00717    reply_str= pu_489_rpl;
00718 
00719 error:
00720    
00721    if(sent_reply== 0)
00722    {
00723       if(send_error_reply(msg, reply_code, reply_str)< 0)
00724       {
00725          LM_ERR("failed to send reply on error case\n");
00726       }
00727    }
00728 
00729    if(subs.pres_uri.s)  
00730       pkg_free(subs.pres_uri.s);
00731    
00732    if(subs.auth_rules_doc)
00733    {
00734       if(subs.auth_rules_doc->s)
00735          pkg_free(subs.auth_rules_doc->s);
00736       pkg_free(subs.auth_rules_doc);
00737    }
00738    if(reason.s)
00739       pkg_free(reason.s);
00740 
00741    if(((!server_address.s) ||(server_address.len== 0))&& subs.local_contact.s)
00742    {
00743       pkg_free(subs.local_contact.s);
00744    }
00745    if(subs.record_route.s)
00746       pkg_free(subs.record_route.s);
00747 
00748    return -1;
00749 
00750 }
00751 
00752 
00753 int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int mexp,
00754       int* to_tag_gen, str scontact)
00755 {
00756    str rec_route= {0, 0};
00757    int rt  = 0;
00758    str* contact= NULL;
00759    contact_body_t *b;
00760    struct to_body *pto, *pfrom = NULL, TO;
00761    int lexpire;
00762    str rtag_value;
00763    struct sip_uri uri;
00764 
00765    /* examine the expire header field */
00766    if(msg->expires && msg->expires->body.len > 0)
00767    {
00768       if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
00769       {
00770          LM_ERR("cannot parse Expires header\n");
00771          goto error;
00772       }
00773       lexpire = ((exp_body_t*)msg->expires->parsed)->val;
00774       LM_DBG("'Expires' header found, value= %d\n", lexpire);
00775 
00776    }
00777    else 
00778    {
00779       LM_DBG("'expires' not found; default=%d\n",subs->event->default_expires);
00780       lexpire = subs->event->default_expires;
00781    }
00782    if(lexpire > mexp)
00783       lexpire = mexp;
00784 
00785    subs->expires = lexpire;
00786 
00787    if( msg->to==NULL || msg->to->body.s==NULL)
00788    {
00789       LM_ERR("cannot parse TO header\n");
00790       goto error;
00791    }
00792    /* examine the to header */
00793    if(msg->to->parsed != NULL)
00794    {
00795       pto = (struct to_body*)msg->to->parsed;
00796       LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",pto->uri.len,pto->uri.s);
00797    }
00798    else
00799    {
00800       memset( &TO , 0, sizeof(TO) );
00801       if( !parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO));
00802       {
00803          LM_DBG("'To' header NOT parsed\n");
00804          goto error;
00805       }
00806       pto = &TO;
00807    }
00808 
00809    if( pto->parsed_uri.user.s && pto->parsed_uri.host.s &&
00810       pto->parsed_uri.user.len && pto->parsed_uri.host.len)
00811    {
00812       subs->to_user = pto->parsed_uri.user;
00813       subs->to_domain = pto->parsed_uri.host;
00814    }
00815    else
00816    {
00817       if(parse_uri(pto->uri.s, pto->uri.len, &uri)< 0)
00818       {
00819          LM_ERR("while parsing uri\n");
00820          goto error;
00821       }
00822       subs->to_user = uri.user;
00823       subs->to_domain = uri.host;
00824    }
00825 
00826    /* examine the from header */
00827    if (!msg->from || !msg->from->body.s)
00828    {
00829       LM_DBG("cannot find 'from' header!\n");
00830       goto error;
00831    }
00832    if (msg->from->parsed == NULL)
00833    {
00834       LM_DBG("'From' header not parsed\n");
00835       /* parsing from header */
00836       if ( parse_from_header( msg )<0 ) 
00837       {
00838          LM_DBG("cannot parse From header\n");
00839          goto error;
00840       }
00841    }
00842    pfrom = (struct to_body*)msg->from->parsed;
00843    
00844    if( pfrom->parsed_uri.user.s && pfrom->parsed_uri.host.s && 
00845       pfrom->parsed_uri.user.len && pfrom->parsed_uri.host.len)
00846    {
00847       subs->from_user = pfrom->parsed_uri.user;
00848       subs->from_domain = pfrom->parsed_uri.host;
00849    }
00850    else
00851    {
00852       if(parse_uri(pfrom->uri.s, pfrom->uri.len, &uri)< 0)
00853       {
00854          LM_ERR("while parsing uri\n");
00855          goto error;
00856       }
00857       subs->from_user = uri.user;
00858       subs->from_domain = uri.host;
00859    }
00860 
00861    /* get to_tag if the message does not have a to_tag*/
00862    if (pto->tag_value.s==NULL || pto->tag_value.len==0 )
00863    {  
00864       LM_DBG("generating to_tag\n");
00865       *to_tag_gen = 1;
00866       rtag_value.len = 0;
00867       if(slb.get_reply_totag(msg, &rtag_value)<0 || rtag_value.len <= 0)
00868       {
00869          LM_ERR("while creating to_tag\n");
00870          goto error;
00871       }
00872    }
00873    else
00874    {
00875       *to_tag_gen = 0;
00876       rtag_value=pto->tag_value;
00877    }
00878    subs->to_tag = rtag_value;
00879 
00880    if( msg->callid==NULL || msg->callid->body.s==NULL)
00881    {
00882       LM_ERR("cannot parse callid header\n");
00883       goto error;
00884    }
00885    subs->callid = msg->callid->body;
00886 
00887    if( msg->cseq==NULL || msg->cseq->body.s==NULL)
00888    {
00889       LM_ERR("cannot parse cseq header\n");
00890       goto error;
00891    }
00892    if (str2int( &(get_cseq(msg)->number), &subs->remote_cseq)!=0 )
00893    {
00894       LM_ERR("cannot parse cseq number\n");
00895       goto error;
00896    }
00897    if( msg->contact==NULL || msg->contact->body.s==NULL)
00898    {
00899       LM_ERR("cannot parse contact header\n");
00900       goto error;
00901    }
00902    if( parse_contact(msg->contact) <0 )
00903    {
00904       LM_ERR(" cannot parse contact"
00905             " header\n");
00906       goto error;
00907    }
00908    b= (contact_body_t* )msg->contact->parsed;
00909 
00910    if(b == NULL)
00911    {
00912       LM_ERR("cannot parse contact header\n");
00913       goto error;
00914    }
00915    subs->contact = b->contacts->uri;
00916    
00917    LM_DBG("subs->contact= %.*s - len = %d\n",subs->contact.len,
00918          subs->contact.s, subs->contact.len);   
00919 
00920     if(subs->event->evp->parsed== EVENT_DIALOG_SLA)
00921     {
00922         /* user_contact@from_domain */
00923         if(parse_uri(subs->contact.s, subs->contact.len, &uri)< 0)
00924         {
00925             LM_ERR("failed to parse contact uri\n");
00926             goto error;
00927         }
00928         if(uandd_to_uri(uri.user, subs->from_domain, &subs->pres_uri)< 0)
00929         {
00930             LM_ERR("failed to construct uri\n");
00931             goto error;
00932         }
00933         LM_DBG("&&&&&&&&&&&&&&& dialog pres_uri= %.*s\n",subs->pres_uri.len, subs->pres_uri.s);
00934     }
00935 
00936 
00937    /*process record route and add it to a string*/
00938    if(*to_tag_gen && msg->record_route!=NULL)
00939    {
00940       rt = print_rr_body(msg->record_route, &rec_route, 0, 0);
00941       if(rt != 0)
00942       {
00943          LM_ERR("processing the record route [%d]\n", rt);  
00944          rec_route.s=NULL;
00945          rec_route.len=0;
00946       // goto error;
00947       }
00948    }
00949    subs->record_route = rec_route;
00950          
00951    subs->sockinfo_str= msg->rcv.bind_address->sock_str;
00952 
00953    if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
00954    {
00955       LM_ERR("no from tag value present\n");
00956       goto error;
00957    }
00958    subs->from_tag = pfrom->tag_value;
00959 
00960    subs->version = 0;
00961    
00962    if((!scontact.s) || (scontact.len== 0))
00963    {
00964       contact= get_local_contact(msg);
00965       if(contact== NULL)
00966       {
00967          LM_ERR("in function get_local_contact\n");
00968          goto error;
00969       }
00970       subs->local_contact= *contact;
00971    }
00972    else
00973       subs->local_contact= scontact;
00974    
00975    return 0;
00976    
00977 error:
00978 
00979    return -1;
00980 }
00981 
00982 
00983 int get_stored_info(struct sip_msg* msg, subs_t* subs, int* reply_code,
00984       str* reply_str)
00985 {  
00986    str pres_uri= {0, 0}, reason={0, 0};
00987    subs_t* s;
00988    int i;
00989    unsigned int hash_code;
00990 
00991    /* first try to_user== pres_user and to_domain== pres_domain */
00992 
00993     if(subs->pres_uri.s == NULL)
00994     {
00995        uandd_to_uri(subs->to_user, subs->to_domain, &pres_uri);
00996        if(pres_uri.s== NULL)
00997        {
00998           LM_ERR("creating uri from user and domain\n");
00999           return -1;
01000        }
01001     }
01002     else
01003         pres_uri = subs->pres_uri;
01004 
01005    hash_code= core_hash(&pres_uri, &subs->event->name, shtable_size);
01006    lock_get(&subs_htable[hash_code].lock);
01007    i= hash_code;
01008    s= search_shtable(subs_htable, subs->callid, subs->to_tag,
01009          subs->from_tag, hash_code);
01010    if(s)
01011    {
01012       goto found_rec;
01013    }
01014    lock_release(&subs_htable[hash_code].lock);
01015 
01016     if(subs->pres_uri.s)
01017         goto not_found;
01018    
01019     pkg_free(pres_uri.s);
01020    pres_uri.s= NULL;
01021    
01022 
01023     LM_DBG("record not found using R-URI search iteratively\n");
01024    /* take one row at a time */
01025    for(i= 0; i< shtable_size; i++)
01026    {
01027       lock_get(&subs_htable[i].lock);
01028       s= search_shtable(subs_htable, subs->callid,subs->to_tag,subs->from_tag, i);
01029       if(s && s->event->evp->parsed!= EVENT_DIALOG_SLA)
01030       {
01031          pres_uri.s= (char*)pkg_malloc(s->pres_uri.len* sizeof(char));
01032          if(pres_uri.s== NULL)
01033          {
01034             lock_release(&subs_htable[i].lock);
01035             ERR_MEM(PKG_MEM_STR);
01036          }
01037          memcpy(pres_uri.s, s->pres_uri.s, s->pres_uri.len);
01038          pres_uri.len= s->pres_uri.len;
01039          goto found_rec;
01040       }
01041       lock_release(&subs_htable[i].lock);
01042    }
01043 
01044    if(fallback2db)
01045    {
01046       return get_database_info(msg, subs, reply_code, reply_str); 
01047    }
01048 
01049 not_found:
01050 
01051    LM_ERR("record not found in hash_table\n");
01052    *reply_code= 481;
01053    *reply_str= pu_481_rpl;
01054 
01055    return -1;
01056 
01057 found_rec:
01058    
01059    LM_DBG("Record found in hash_table\n");
01060    
01061    if(s->event->evp->parsed!= EVENT_DIALOG_SLA)
01062       subs->pres_uri= pres_uri;
01063    
01064    subs->version = s->version;
01065    subs->status= s->status;
01066    if(s->reason.s && s->reason.len)
01067    {  
01068       reason.s= (char*)pkg_malloc(s->reason.len* sizeof(char));
01069       if(reason.s== NULL)
01070       {
01071          lock_release(&subs_htable[i].lock);
01072          ERR_MEM(PKG_MEM_STR);
01073       }
01074       memcpy(reason.s, s->reason.s, s->reason.len);
01075       reason.len= s->reason.len;
01076       subs->reason= reason;
01077    }
01078    if(s->record_route.s && s->record_route.len)
01079    {
01080       subs->record_route.s= (char*)pkg_malloc
01081          (s->record_route.len* sizeof(char));
01082       if(subs->record_route.s== NULL)
01083       {
01084          ERR_MEM(PKG_MEM_STR);
01085       }
01086       memcpy(subs->record_route.s, s->record_route.s, s->record_route.len);
01087       subs->record_route.len= s->record_route.len;
01088    }
01089 
01090    subs->local_cseq= s->local_cseq;
01091    
01092    if(subs->remote_cseq<= s->remote_cseq)
01093    {
01094       LM_ERR("wrong sequence number;received: %d - stored: %d\n",
01095             subs->remote_cseq, s->remote_cseq);
01096       
01097       *reply_code= 400;
01098       *reply_str= pu_400_rpl;
01099 
01100       lock_release(&subs_htable[i].lock);
01101       goto error;
01102    }  
01103    lock_release(&subs_htable[i].lock);
01104 
01105    return 0;
01106 
01107 error:
01108    if(subs->reason.s)
01109       pkg_free(subs->reason.s);
01110    subs->reason.s= NULL;
01111    if(subs->record_route.s)
01112       pkg_free(subs->record_route.s);
01113    subs->record_route.s= NULL;
01114    return -1;
01115 }
01116 
01117 int get_database_info(struct sip_msg* msg, subs_t* subs, int* reply_code, str* reply_str)
01118 {  
01119    db_key_t query_cols[10];
01120    db_val_t query_vals[10];
01121    db_key_t result_cols[9];
01122    db_res_t *result= NULL;
01123    db_row_t *row ;   
01124    db_val_t *row_vals ;
01125    int n_query_cols = 0;
01126    int n_result_cols = 0;
01127    int remote_cseq_col= 0, local_cseq_col= 0, status_col, reason_col;
01128    int record_route_col, version_col;
01129    int pres_uri_col;
01130    unsigned int remote_cseq;
01131    str pres_uri, record_route;
01132    str reason;
01133 
01134    query_cols[n_query_cols] = &str_to_user_col;
01135    query_vals[n_query_cols].type = DB_STR;
01136    query_vals[n_query_cols].nul = 0;
01137    query_vals[n_query_cols].val.str_val = subs->to_user;
01138    n_query_cols++;
01139    
01140    query_cols[n_query_cols] = &str_to_domain_col;
01141    query_vals[n_query_cols].type = DB_STR;
01142    query_vals[n_query_cols].nul = 0;
01143    query_vals[n_query_cols].val.str_val = subs->to_domain;
01144    n_query_cols++;
01145 
01146    query_cols[n_query_cols] = &str_watcher_username_col;
01147    query_vals[n_query_cols].type = DB_STR;
01148    query_vals[n_query_cols].nul = 0;
01149    query_vals[n_query_cols].val.str_val = subs->from_user;
01150    n_query_cols++;
01151    
01152    query_cols[n_query_cols] = &str_watcher_domain_col;
01153    query_vals[n_query_cols].type = DB_STR;
01154    query_vals[n_query_cols].nul = 0;
01155    query_vals[n_query_cols].val.str_val = subs->from_domain;
01156    n_query_cols++;
01157 
01158    query_cols[n_query_cols] = &str_event_col;
01159    query_vals[n_query_cols].type = DB_STR;
01160    query_vals[n_query_cols].nul = 0;
01161    query_vals[n_query_cols].val.str_val = subs->event->name;
01162    n_query_cols++;
01163 
01164    query_cols[n_query_cols] = &str_event_id_col;
01165    query_vals[n_query_cols].type = DB_STR;
01166    query_vals[n_query_cols].nul = 0;
01167    if( subs->event_id.s != NULL)
01168    {
01169       query_vals[n_query_cols].val.str_val.s = subs->event_id.s;
01170       query_vals[n_query_cols].val.str_val.len = subs->event_id.len;
01171    } else {
01172       query_vals[n_query_cols].val.str_val.s = "";
01173       query_vals[n_query_cols].val.str_val.len = 0;
01174    }
01175    n_query_cols++;
01176    
01177    query_cols[n_query_cols] = &str_callid_col;
01178    query_vals[n_query_cols].type = DB_STR;
01179    query_vals[n_query_cols].nul = 0;
01180    query_vals[n_query_cols].val.str_val = subs->callid;
01181    n_query_cols++;
01182 
01183    query_cols[n_query_cols] = &str_to_tag_col;
01184    query_vals[n_query_cols].type = DB_STR;
01185    query_vals[n_query_cols].nul = 0;
01186    query_vals[n_query_cols].val.str_val = subs->to_tag;
01187    n_query_cols++;
01188 
01189    query_cols[n_query_cols] = &str_from_tag_col;
01190    query_vals[n_query_cols].type = DB_STR;
01191    query_vals[n_query_cols].nul = 0;
01192    query_vals[n_query_cols].val.str_val = subs->from_tag;
01193    n_query_cols++;
01194 
01195    result_cols[pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
01196    result_cols[remote_cseq_col=n_result_cols++] = &str_remote_cseq_col;
01197    result_cols[local_cseq_col=n_result_cols++] = &str_local_cseq_col;
01198    result_cols[status_col=n_result_cols++] = &str_status_col;
01199    result_cols[reason_col=n_result_cols++] = &str_reason_col;
01200    result_cols[record_route_col=n_result_cols++] = &str_record_route_col;
01201    result_cols[version_col=n_result_cols++] = &str_version_col;
01202    
01203    if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0) 
01204    {
01205       LM_ERR("unsuccessful use_table sql operation\n");
01206       return -1;
01207    }
01208    
01209    if (pa_dbf.query (pa_db, query_cols, 0, query_vals,
01210        result_cols, n_query_cols, n_result_cols, 0,  &result) < 0) 
01211    {
01212       LM_ERR("querying subscription dialog\n");
01213       if(result)
01214          pa_dbf.free_result(pa_db, result);
01215       return -1;
01216    }
01217    if(result== NULL)
01218       return -1;
01219 
01220    if(result && result->n <=0)
01221    {
01222       LM_ERR("No matching subscription dialog found in database\n");
01223       
01224       pa_dbf.free_result(pa_db, result);
01225       *reply_code= 481;
01226       *reply_str= pu_481_rpl;
01227 
01228       return -1;
01229    }
01230 
01231    row = &result->rows[0];
01232    row_vals = ROW_VALUES(row);
01233    remote_cseq= row_vals[remote_cseq_col].val.int_val;
01234    
01235    if(subs->remote_cseq<= remote_cseq)
01236    {
01237       LM_ERR("wrong sequence number received: %d - stored: %d\n",
01238             subs->remote_cseq, remote_cseq);
01239       *reply_code= 400;
01240       *reply_str= pu_400_rpl;
01241       pa_dbf.free_result(pa_db, result);
01242       return -1;
01243    }
01244    
01245    subs->status= row_vals[status_col].val.int_val;
01246    reason.s= (char*)row_vals[reason_col].val.string_val;
01247    if(reason.s)
01248    {
01249       reason.len= strlen(reason.s);
01250       subs->reason.s= (char*)pkg_malloc(reason.len* sizeof(char));
01251       if(subs->reason.s== NULL)
01252       {
01253          ERR_MEM(PKG_MEM_STR);
01254       }
01255       memcpy(subs->reason.s, reason.s, reason.len);
01256       subs->reason.len= reason.len;
01257    }
01258 
01259    subs->local_cseq= row_vals[local_cseq_col].val.int_val;
01260    subs->version= row_vals[version_col].val.int_val;
01261 
01262    if(subs->event->evp->parsed!= EVENT_DIALOG_SLA)
01263    {
01264       pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
01265       pres_uri.len= strlen(pres_uri.s);
01266       subs->pres_uri.s= (char*)pkg_malloc(pres_uri.len* sizeof(char));
01267       if(subs->pres_uri.s== NULL)
01268       {  
01269          if(subs->reason.s)
01270             pkg_free(subs->reason.s);
01271          ERR_MEM(PKG_MEM_STR);
01272       }
01273       memcpy(subs->pres_uri.s, pres_uri.s, pres_uri.len);
01274       subs->pres_uri.len= pres_uri.len;
01275    }
01276 
01277    record_route.s= (char*)row_vals[record_route_col].val.string_val;
01278    if(record_route.s)
01279    {
01280       record_route.len= strlen(record_route.s);
01281       subs->record_route.s= (char*)pkg_malloc(record_route.len*sizeof(char));
01282       if(subs->record_route.s== NULL)
01283       {
01284          ERR_MEM(PKG_MEM_STR);
01285       }
01286       memcpy(subs->record_route.s, record_route.s, record_route.len);
01287       subs->record_route.len= record_route.len;
01288    }
01289 
01290    pa_dbf.free_result(pa_db, result);
01291    result= NULL;
01292 
01293    return 0;
01294 error:
01295    if(result)
01296       pa_dbf.free_result(pa_db, result);
01297 
01298    return -1;
01299 
01300 }
01301 
01302 
01303 int handle_expired_subs(subs_t* s)
01304 {
01305    /* send Notify with state=terminated;reason=timeout */
01306    
01307    s->status= TERMINATED_STATUS;
01308    s->reason.s= "timeout";
01309    s->reason.len= 7;
01310    s->expires= 0;
01311 
01312    if(send_notify_request(s, NULL, NULL, 1)< 0)
01313    {
01314       LM_ERR("send Notify not successful\n");
01315       return -1;
01316    }
01317    
01318    return 0;
01319 
01320 }
01321 
01322 void timer_db_update(unsigned int ticks,void *param)
01323 {  
01324    int no_lock=0;
01325 
01326    if(ticks== 0 && param == NULL)
01327       no_lock= 1;
01328    
01329    if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
01330    {
01331       LM_ERR("sql use table failed\n");
01332       return;
01333    }
01334 
01335    update_db_subs(pa_db, pa_dbf, subs_htable, 
01336          shtable_size, no_lock, handle_expired_subs);
01337 
01338 }
01339 
01340 void update_db_subs(db_con_t *db,db_func_t dbf, shtable_t hash_table,
01341    int htable_size, int no_lock, handle_expired_func_t handle_expired_func)
01342 {  
01343    db_key_t query_cols[22], update_cols[7];
01344    db_val_t query_vals[22], update_vals[7];
01345    db_op_t update_ops[1];
01346    subs_t* del_s;
01347    int pres_uri_col, to_user_col, to_domain_col, from_user_col, from_domain_col,
01348       callid_col, totag_col, fromtag_col, event_col,status_col, event_id_col, 
01349       local_cseq_col, remote_cseq_col, expires_col, record_route_col, 
01350       contact_col, local_contact_col, version_col,socket_info_col,reason_col;
01351    int u_expires_col, u_local_cseq_col, u_remote_cseq_col, u_version_col, 
01352       u_reason_col, u_status_col; 
01353    int i;
01354    subs_t* s= NULL, *prev_s= NULL;
01355    int n_query_cols= 0, n_update_cols= 0;
01356    int n_query_update;
01357 
01358    query_cols[pres_uri_col= n_query_cols] =&str_presentity_uri_col;
01359    query_vals[pres_uri_col].type = DB_STR;
01360    query_vals[pres_uri_col].nul = 0;
01361    n_query_cols++;
01362    
01363    query_cols[callid_col= n_query_cols] =&str_callid_col;
01364    query_vals[callid_col].type = DB_STR;
01365    query_vals[callid_col].nul = 0;
01366    n_query_cols++;
01367 
01368    query_cols[totag_col= n_query_cols] =&str_to_tag_col;
01369    query_vals[totag_col].type = DB_STR;
01370    query_vals[totag_col].nul = 0;
01371    n_query_cols++;
01372 
01373    query_cols[fromtag_col= n_query_cols] =&str_from_tag_col;
01374    query_vals[fromtag_col].type = DB_STR;
01375    query_vals[fromtag_col].nul = 0;
01376    n_query_cols++;
01377 
01378    n_query_update= n_query_cols;
01379 
01380    query_cols[to_user_col= n_query_cols] =&str_to_user_col;
01381    query_vals[to_user_col].type = DB_STR;
01382    query_vals[to_user_col].nul = 0;
01383    n_query_cols++;
01384 
01385    query_cols[to_domain_col= n_query_cols] =&str_to_domain_col;
01386    query_vals[to_domain_col].type = DB_STR;
01387    query_vals[to_domain_col].nul = 0;
01388    n_query_cols++;
01389    
01390    query_cols[from_user_col= n_query_cols] =&str_watcher_username_col;
01391    query_vals[from_user_col].type = DB_STR;
01392    query_vals[from_user_col].nul = 0;
01393    n_query_cols++;
01394 
01395    query_cols[from_domain_col= n_query_cols] =&str_watcher_domain_col;
01396    query_vals[from_domain_col].type = DB_STR;
01397    query_vals[from_domain_col].nul = 0;
01398    n_query_cols++;
01399 
01400    query_cols[event_col= n_query_cols] =&str_event_col;
01401    query_vals[event_col].type = DB_STR;
01402    query_vals[event_col].nul = 0;
01403    n_query_cols++;   
01404 
01405    query_cols[event_id_col= n_query_cols] =&str_event_id_col;
01406    query_vals[event_id_col].type = DB_STR;
01407    query_vals[event_id_col].nul = 0;
01408    n_query_cols++;
01409 
01410    query_cols[local_cseq_col= n_query_cols]=&str_local_cseq_col;
01411    query_vals[local_cseq_col].type = DB_INT;
01412    query_vals[local_cseq_col].nul = 0;
01413    n_query_cols++;
01414 
01415    query_cols[remote_cseq_col= n_query_cols]=&str_remote_cseq_col;
01416    query_vals[remote_cseq_col].type = DB_INT;
01417    query_vals[remote_cseq_col].nul = 0;
01418    n_query_cols++;
01419 
01420    query_cols[expires_col= n_query_cols] =&str_expires_col;
01421    query_vals[expires_col].type = DB_INT;
01422    query_vals[expires_col].nul = 0;
01423    n_query_cols++;
01424 
01425    query_cols[status_col= n_query_cols] =&str_status_col;
01426    query_vals[status_col].type = DB_INT;
01427    query_vals[status_col].nul = 0;
01428    n_query_cols++;
01429 
01430    query_cols[reason_col= n_query_cols] =&str_reason_col;
01431    query_vals[reason_col].type = DB_STR;
01432    query_vals[reason_col].nul = 0;
01433    n_query_cols++;
01434 
01435    query_cols[record_route_col= n_query_cols] =&str_record_route_col;
01436    query_vals[record_route_col].type = DB_STR;
01437    query_vals[record_route_col].nul = 0;
01438    n_query_cols++;
01439    
01440    query_cols[contact_col= n_query_cols] =&str_contact_col;
01441    query_vals[contact_col].type = DB_STR;
01442    query_vals[contact_col].nul = 0;
01443    n_query_cols++;
01444 
01445    query_cols[local_contact_col= n_query_cols] =&str_local_contact_col;
01446    query_vals[local_contact_col].type = DB_STR;
01447    query_vals[local_contact_col].nul = 0;
01448    n_query_cols++;
01449 
01450    query_cols[socket_info_col= n_query_cols] =&str_socket_info_col;
01451    query_vals[socket_info_col].type = DB_STR;
01452    query_vals[socket_info_col].nul = 0;
01453    n_query_cols++;
01454 
01455    query_cols[version_col= n_query_cols]=&str_version_col;
01456    query_vals[version_col].type = DB_INT;
01457    query_vals[version_col].nul = 0;
01458    n_query_cols++;
01459 
01460    /* cols and values used for update */
01461    update_cols[u_expires_col= n_update_cols]= &str_expires_col;
01462    update_vals[u_expires_col].type = DB_INT;
01463    update_vals[u_expires_col].nul = 0;
01464    n_update_cols++;
01465 
01466    update_cols[u_status_col= n_update_cols]= &str_status_col;
01467    update_vals[u_status_col].type = DB_INT;
01468    update_vals[u_status_col].nul = 0;
01469    n_update_cols++;
01470 
01471    update_cols[u_reason_col= n_update_cols]= &str_reason_col;
01472    update_vals[u_reason_col].type = DB_STR;
01473    update_vals[u_reason_col].nul = 0;
01474    n_update_cols++;
01475 
01476    update_cols[u_remote_cseq_col= n_update_cols]= &str_remote_cseq_col;
01477    update_vals[u_remote_cseq_col].type = DB_INT;
01478    update_vals[u_remote_cseq_col].nul = 0;
01479    n_update_cols++;
01480 
01481    update_cols[u_local_cseq_col= n_update_cols]= &str_local_cseq_col;
01482    update_vals[u_local_cseq_col].type = DB_INT;
01483    update_vals[u_local_cseq_col].nul = 0;
01484    n_update_cols++;
01485    
01486    update_cols[u_version_col= n_update_cols]= &str_version_col;
01487    update_vals[u_version_col].type = DB_INT;
01488    update_vals[u_version_col].nul = 0;
01489    n_update_cols++;
01490 
01491 
01492    if(db== NULL)
01493    {
01494       LM_ERR("null database connection\n");
01495       return;
01496    }
01497    for(i=0; i<htable_size; i++) 
01498    {
01499       if(!no_lock)
01500          lock_get(&hash_table[i].lock);   
01501 
01502       prev_s= hash_table[i].entries;
01503       s= prev_s->next;
01504    
01505       while(s)
01506       {
01507          printf_subs(s);
01508          if(s->expires < (int)time(NULL)- 50)   
01509          {
01510             LM_DBG("Found expired record\n");
01511             if(!no_lock)
01512             {
01513                if(handle_expired_func(s)< 0)
01514                {
01515                   LM_ERR("in function handle_expired_record\n");
01516                   if(!no_lock)
01517                      lock_release(&hash_table[i].lock);  
01518                   return ;
01519                }
01520             }
01521             del_s= s;   
01522             s= s->next;
01523             prev_s->next= s;
01524             
01525             /* need for a struct free/destroy? */
01526             if (del_s->contact.s)
01527                shm_free(del_s->contact.s);
01528 
01529             shm_free(del_s);
01530             continue;
01531          }
01532          switch(s->db_flag)
01533          {
01534             case NO_UPDATEDB_FLAG:
01535             {
01536                LM_DBG("NO_UPDATEDB_FLAG\n");
01537                break;           
01538             }
01539             case UPDATEDB_FLAG:
01540             {
01541                LM_DBG("UPDATEDB_FLAG\n");
01542 
01543                query_vals[pres_uri_col].val.str_val= s->pres_uri;
01544                query_vals[callid_col].val.str_val= s->callid;
01545                query_vals[totag_col].val.str_val= s->to_tag;
01546                query_vals[fromtag_col].val.str_val= s->from_tag;
01547             
01548                update_vals[u_expires_col].val.int_val= s->expires;
01549                update_vals[u_local_cseq_col].val.int_val= s->local_cseq;
01550                update_vals[u_remote_cseq_col].val.int_val= s->remote_cseq;
01551                update_vals[u_version_col].val.int_val= s->version;
01552                update_vals[u_status_col].val.int_val= s->status;
01553                update_vals[u_reason_col].val.str_val= s->reason;
01554 
01555                if(dbf.update(db, query_cols, 0, query_vals, update_cols, 
01556                         update_vals, n_query_update, n_update_cols)< 0)
01557                {
01558                   LM_ERR("updating in database\n");
01559                   if(!no_lock)
01560                      lock_release(&hash_table[i].lock);  
01561                   return ;
01562                }
01563                break;
01564             }
01565             case  INSERTDB_FLAG:
01566             {
01567                LM_DBG("INSERTDB_FLAG\n");
01568 
01569                query_vals[pres_uri_col].val.str_val= s->pres_uri;
01570                query_vals[callid_col].val.str_val= s->callid;
01571                query_vals[totag_col].val.str_val= s->to_tag;
01572                query_vals[fromtag_col].val.str_val= s->from_tag;
01573                query_vals[to_user_col].val.str_val = s->to_user;
01574                query_vals[to_domain_col].val.str_val = s->to_domain;
01575                query_vals[from_user_col].val.str_val = s->from_user;
01576                query_vals[from_domain_col].val.str_val = s->from_domain;
01577                query_vals[event_col].val.str_val = s->event->name;
01578                query_vals[event_id_col].val.str_val = s->event_id;
01579                query_vals[local_cseq_col].val.int_val= s->local_cseq;
01580                query_vals[remote_cseq_col].val.int_val= s->remote_cseq;
01581                query_vals[expires_col].val.int_val = s->expires;
01582                query_vals[record_route_col].val.str_val = s->record_route;
01583                query_vals[contact_col].val.str_val = s->contact;
01584                query_vals[local_contact_col].val.str_val = s->local_contact;
01585                query_vals[version_col].val.int_val= s->version;
01586                query_vals[status_col].val.int_val= s->status;
01587                query_vals[reason_col].val.str_val= s->reason;
01588                query_vals[socket_info_col].val.str_val= s->sockinfo_str;
01589             
01590                if(dbf.insert(db,query_cols,query_vals,n_query_cols )<0)
01591                {
01592                   LM_ERR("unsuccessful sql insert\n");
01593                   if(!no_lock)
01594                      lock_release(&hash_table[i].lock);
01595                   return ;
01596                }
01597                break;                              
01598             }
01599 
01600          }
01601          s->db_flag= NO_UPDATEDB_FLAG; 
01602          prev_s= s;
01603          s= s->next;
01604       }
01605       if(!no_lock)
01606          lock_release(&hash_table[i].lock);  
01607    }
01608 
01609    update_vals[0].val.int_val= (int)time(NULL)- 10;
01610    update_ops[0]= OP_LT;
01611    if(dbf.delete(db, update_cols, update_ops, update_vals, 1) < 0)
01612    {
01613       LM_ERR("deleting expired information from database\n");
01614    }
01615 
01616 }
01617 
01618 int restore_db_subs(void)
01619 {
01620    db_key_t result_cols[22]; 
01621    db_res_t *res= NULL;
01622    db_row_t *row = NULL;   
01623    db_val_t *row_vals= NULL;
01624    int i;
01625    int n_result_cols= 0;
01626    int pres_uri_col, expires_col, from_user_col, from_domain_col,to_user_col; 
01627    int callid_col,totag_col,fromtag_col,to_domain_col,sockinfo_col,reason_col;
01628    int event_col,contact_col,record_route_col, event_id_col, status_col;
01629    int remote_cseq_col, local_cseq_col, local_contact_col, version_col;
01630    subs_t s;
01631    str ev_sname;
01632    pres_ev_t* event= NULL;
01633    event_t parsed_event;
01634    unsigned int expires;
01635    unsigned int hash_code;
01636 
01637    result_cols[pres_uri_col=n_result_cols++] =&str_presentity_uri_col;
01638    result_cols[expires_col=n_result_cols++]=&str_expires_col;
01639    result_cols[event_col=n_result_cols++] =&str_event_col;
01640    result_cols[event_id_col=n_result_cols++]=&str_event_id_col;
01641    result_cols[to_user_col=n_result_cols++]  =&str_to_user_col;
01642    result_cols[to_domain_col=n_result_cols++]   =&str_to_domain_col;
01643    result_cols[from_user_col=n_result_cols++]   =&str_watcher_username_col;
01644    result_cols[from_domain_col=n_result_cols++]=&str_watcher_domain_col;
01645    result_cols[callid_col=n_result_cols++] =&str_callid_col;
01646    result_cols[totag_col=n_result_cols++] =&str_to_tag_col;
01647    result_cols[fromtag_col=n_result_cols++]=&str_from_tag_col;
01648    result_cols[local_cseq_col= n_result_cols++] =&str_local_cseq_col;
01649    result_cols[remote_cseq_col= n_result_cols++]   =&str_remote_cseq_col;
01650    result_cols[record_route_col= n_result_cols++]  =&str_record_route_col;
01651    result_cols[sockinfo_col= n_result_cols++]   =&str_socket_info_col;
01652    result_cols[contact_col= n_result_cols++] =&str_contact_col;
01653    result_cols[local_contact_col= n_result_cols++] =&str_local_contact_col;
01654    result_cols[version_col= n_result_cols++] =&str_version_col;
01655    result_cols[status_col= n_result_cols++]  =&str_status_col;
01656    result_cols[reason_col= n_result_cols++]  =&str_reason_col;
01657    
01658    if(!pa_db)
01659    {
01660       LM_ERR("null database connection\n");
01661       return -1;
01662    }
01663 
01664    if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
01665    {
01666       LM_ERR("in use table\n");
01667       return -1;
01668    }
01669 
01670    if(pa_dbf.query(pa_db,0, 0, 0, result_cols,0, n_result_cols, 0,&res)< 0)
01671    {
01672       LM_ERR("while querrying table\n");
01673       if(res)
01674       {
01675          pa_dbf.free_result(pa_db, res);
01676          res = NULL;
01677       }
01678       return -1;
01679    }
01680    if(res== NULL)
01681       return -1;
01682 
01683    if(res->n<=0)
01684    {
01685       LM_INFO("The query returned no result\n");
01686       pa_dbf.free_result(pa_db, res);
01687       res = NULL;
01688       return 0;
01689    }
01690 
01691    LM_DBG("found %d db entries\n", res->n);
01692 
01693    for(i =0 ; i< res->n ; i++)
01694    {
01695       row = &res->rows[i];
01696       row_vals = ROW_VALUES(row);
01697       memset(&s, 0, sizeof(subs_t));
01698 
01699       expires= row_vals[expires_col].val.int_val;
01700       
01701       if(expires< (int)time(NULL))
01702          continue;
01703    
01704       s.pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
01705       s.pres_uri.len= strlen(s.pres_uri.s);
01706       
01707       s.to_user.s=(char*)row_vals[to_user_col].val.string_val;
01708       s.to_user.len= strlen(s.to_user.s);
01709 
01710       s.to_domain.s=(char*)row_vals[to_domain_col].val.string_val;
01711       s.to_domain.len= strlen(s.to_domain.s);
01712 
01713       s.from_user.s=(char*)row_vals[from_user_col].val.string_val;
01714       s.from_user.len= strlen(s.from_user.s);
01715       
01716       s.from_domain.s=(char*)row_vals[from_domain_col].val.string_val;
01717       s.from_domain.len= strlen(s.from_domain.s);
01718 
01719       s.to_tag.s=(char*)row_vals[totag_col].val.string_val;
01720       s.to_tag.len= strlen(s.to_tag.s);
01721 
01722       s.from_tag.s=(char*)row_vals[fromtag_col].val.string_val;
01723       s.from_tag.len= strlen(s.from_tag.s);
01724 
01725       s.callid.s=(char*)row_vals[callid_col].val.string_val;
01726       s.callid.len= strlen(s.callid.s);
01727 
01728       ev_sname.s= (char*)row_vals[event_col].val.string_val;
01729       ev_sname.len= strlen(ev_sname.s);
01730       
01731       event= contains_event(&ev_sname, &parsed_event);
01732       if(event== NULL)
01733       {
01734          LM_DBG("insert a new event structure in the list waiting"
01735                " to be filled in\n");
01736    
01737          /*insert a new event structure in the list waiting to be filled in*/
01738          event= (pres_ev_t*)shm_malloc(sizeof(pres_ev_t));
01739          if(event== NULL)
01740          {
01741             free_event_params(parsed_event.params, PKG_MEM_TYPE);
01742             ERR_MEM(SHM_MEM_STR);
01743          }
01744          memset(event, 0, sizeof(pres_ev_t));
01745          event->name.s= (char*)shm_malloc(ev_sname.len* sizeof(char));
01746          if(event->name.s== NULL)
01747          {
01748             free_event_params(parsed_event.params, PKG_MEM_TYPE);
01749             ERR_MEM(SHM_MEM_STR);
01750          }
01751          memcpy(event->name.s,ev_sname.s, ev_sname.len);
01752          event->name.len= ev_sname.len;
01753          
01754          event->evp= shm_copy_event(&parsed_event);
01755          if(event->evp== NULL)
01756          {
01757             LM_ERR("ERROR copying event_t structure\n");
01758             free_event_params(parsed_event.params, PKG_MEM_TYPE);
01759             goto error;
01760          }
01761          event->next= EvList->events;
01762          EvList->events= event;
01763       }
01764          
01765       free_event_params(parsed_event.params, PKG_MEM_TYPE);
01766 
01767       s.event= event;
01768 
01769       s.event_id.s=(char*)row_vals[event_id_col].val.string_val;
01770       if(s.event_id.s)
01771          s.event_id.len= strlen(s.event_id.s);
01772 
01773       s.remote_cseq= row_vals[remote_cseq_col].val.int_val;
01774       s.local_cseq= row_vals[local_cseq_col].val.int_val;
01775       s.version= row_vals[version_col].val.int_val;
01776       
01777       s.expires= expires- (int)time(NULL);
01778       s.status= row_vals[status_col].val.int_val;
01779 
01780       s.reason.s= (char*)row_vals[reason_col].val.string_val;
01781       if(s.reason.s)
01782          s.reason.len= strlen(s.reason.s);
01783 
01784       s.contact.s=(char*)row_vals[contact_col].val.string_val;
01785       s.contact.len= strlen(s.contact.s);
01786 
01787       s.local_contact.s=(char*)row_vals[local_contact_col].val.string_val;
01788       s.local_contact.len= strlen(s.local_contact.s);
01789    
01790       s.record_route.s=(char*)row_vals[record_route_col].val.string_val;
01791       if(s.record_route.s)
01792          s.record_route.len= strlen(s.record_route.s);
01793    
01794       s.sockinfo_str.s=(char*)row_vals[sockinfo_col].val.string_val;
01795       s.sockinfo_str.len= strlen(s.sockinfo_str.s);
01796 
01797       hash_code= core_hash(&s.pres_uri, &s.event->name, shtable_size);
01798       if(insert_shtable(subs_htable, hash_code, &s)< 0)
01799       {
01800          LM_ERR("adding new record in hash table\n");
01801          goto error;
01802       }
01803    }
01804 
01805    pa_dbf.free_result(pa_db, res);
01806 
01807    /* delete all records */
01808    if(pa_dbf.delete(pa_db, 0,0,0,0)< 0)
01809    {
01810       LM_ERR("deleting all records from database table\n");
01811       return -1;
01812    }
01813 
01814    return 0;
01815 
01816 error:
01817    if(res)
01818       pa_dbf.free_result(pa_db, res);
01819    return -1;
01820 
01821 }
01822 
01823 int refresh_watcher(str* pres_uri, str* watcher_uri, str* event, 
01824       int status, str* reason)
01825 {
01826    unsigned int hash_code;
01827    subs_t* s, *s_copy;
01828    pres_ev_t* ev;    
01829    struct sip_uri uri;
01830    str user, domain;
01831    /* refresh status in subs_htable and send notify */
01832 
01833    ev=   contains_event(event, NULL);
01834    if(ev== NULL)
01835    {
01836       LM_ERR("while searching event in list\n");
01837       return -1;
01838    }
01839 
01840    if(parse_uri(watcher_uri->s, watcher_uri->len, &uri)< 0)
01841    {
01842       LM_ERR("parsing uri\n");
01843       return -1;
01844    }
01845    user= uri.user;
01846    domain= uri.host;
01847 
01848    hash_code= core_hash(pres_uri, event, shtable_size);
01849 
01850    lock_get(&subs_htable[hash_code].lock);
01851 
01852    s= subs_htable[hash_code].entries->next;
01853 
01854    while(s)
01855    {
01856       if(s->event== ev && s->pres_uri.len== pres_uri->len &&
01857          strncmp(s->pres_uri.s, pres_uri->s, pres_uri->len)== 0 &&
01858          s->from_user.len==user.len && strncmp(s->from_user.s,user.s, user.len)==0 &&
01859          s->from_domain.len== domain.len && 
01860          strncmp(s->from_domain.s, domain.s, domain.len)== 0)
01861       {
01862          s->status= status;
01863          if(reason)
01864             s->reason= *reason;
01865          
01866          s_copy= mem_copy_subs(s, PKG_MEM_TYPE);
01867          if(s_copy== NULL)
01868          {
01869             LM_ERR("copying subs_t\n");
01870             lock_release(&subs_htable[hash_code].lock);
01871             return -1;
01872          }
01873          lock_release(&subs_htable[hash_code].lock);
01874          if(notify(s_copy, NULL, NULL, 0)< 0)
01875          {
01876             LM_ERR("in notify function\n");
01877             pkg_free(s_copy);
01878             return -1;
01879          }
01880          pkg_free(s_copy);
01881          lock_get(&subs_htable[hash_code].lock);
01882       }
01883       s= s->next;
01884    }
01885    return 0;
01886 }
01887 
01888 int get_db_subs_auth(subs_t* subs, int* found)
01889 {
01890    db_key_t db_keys[5];
01891    db_val_t db_vals[5];
01892    int n_query_cols= 0; 
01893    db_key_t result_cols[3];
01894    db_res_t *result = NULL;
01895    db_row_t *row ;   
01896    db_val_t *row_vals ;
01897 
01898    db_keys[n_query_cols] =&str_presentity_uri_col;
01899    db_vals[n_query_cols].type = DB_STR;
01900    db_vals[n_query_cols].nul = 0;
01901    db_vals[n_query_cols].val.str_val= subs->pres_uri;
01902    n_query_cols++;
01903 
01904    db_keys[n_query_cols] =&str_watcher_username_col;
01905    db_vals[n_query_cols].type = DB_STR;
01906    db_vals[n_query_cols].nul = 0;
01907    db_vals[n_query_cols].val.str_val = subs->from_user;
01908    n_query_cols++;
01909 
01910    db_keys[n_query_cols] =&str_watcher_domain_col;
01911    db_vals[n_query_cols].type = DB_STR;
01912    db_vals[n_query_cols].nul = 0;
01913    db_vals[n_query_cols].val.str_val = subs->from_domain;
01914    n_query_cols++;
01915    
01916    db_keys[n_query_cols] =&str_event_col;
01917    db_vals[n_query_cols].type = DB_STR;
01918    db_vals[n_query_cols].nul = 0;
01919    db_vals[n_query_cols].val.str_val = subs->event->name;
01920    n_query_cols++;
01921 
01922    result_cols[0] = &str_status_col;
01923    result_cols[1] = &str_reason_col;
01924    
01925    if(pa_dbf.use_table(pa_db, &watchers_table)< 0)
01926    {
01927       LM_ERR("in use table\n");
01928       return -1;
01929    }  
01930 
01931    if(pa_dbf.query(pa_db, db_keys, 0, db_vals, result_cols,
01932                n_query_cols, 2, 0, &result )< 0)
01933    {
01934       LM_ERR("while querying watchers table\n");
01935       if(result)
01936          pa_dbf.free_result(pa_db, result);
01937       return -1;
01938    }
01939    if(result== NULL)
01940       return -1;
01941    
01942    if(result->n<= 0)
01943    {
01944       *found= 0;
01945       pa_dbf.free_result(pa_db, result);
01946       return 0;
01947    }
01948 
01949    *found= 1;
01950    row = &result->rows[0];
01951    row_vals = ROW_VALUES(row);
01952    subs->status= row_vals[0].val.int_val;
01953 
01954    if(row_vals[1].val.string_val)
01955    {
01956 
01957       subs->reason.len= strlen(row_vals[1].val.string_val);
01958       if(subs->reason.len== 0)
01959          subs->reason.s= NULL;
01960       else
01961       {
01962          subs->reason.s= (char*)pkg_malloc(subs->reason.len*sizeof(char));
01963          if(subs->reason.s== NULL)
01964          {
01965             pa_dbf.free_result(pa_db, result);
01966             ERR_MEM(PKG_MEM_STR);
01967          }     
01968          memcpy(subs->reason.s, row_vals[1].val.string_val, subs->reason.len);
01969       }
01970    }
01971    
01972    pa_dbf.free_result(pa_db, result);
01973    return 0;
01974 error:
01975    return -1;
01976 }  
01977 
01978 int insert_db_subs_auth(subs_t* subs)
01979 {
01980    db_key_t db_keys[10];
01981    db_val_t db_vals[10];
01982    int n_query_cols= 0; 
01983 
01984    db_keys[n_query_cols] =&str_presentity_uri_col;
01985    db_vals[n_query_cols].type = DB_STR;
01986    db_vals[n_query_cols].nul = 0;
01987    db_vals[n_query_cols].val.str_val= subs->pres_uri;
01988    n_query_cols++;
01989 
01990    db_keys[n_query_cols] =&str_watcher_username_col;
01991    db_vals[n_query_cols].type = DB_STR;
01992    db_vals[n_query_cols].nul = 0;
01993    db_vals[n_query_cols].val.str_val = subs->from_user;
01994    n_query_cols++;
01995 
01996    db_keys[n_query_cols] =&str_watcher_domain_col;
01997    db_vals[n_query_cols].type = DB_STR;
01998    db_vals[n_query_cols].nul = 0;
01999    db_vals[n_query_cols].val.str_val = subs->from_domain;
02000    n_query_cols++;
02001    
02002    db_keys[n_query_cols] =&str_event_col;
02003    db_vals[n_query_cols].type = DB_STR;
02004    db_vals[n_query_cols].nul = 0;
02005    db_vals[n_query_cols].val.str_val = subs->event->name;
02006    n_query_cols++;
02007 
02008    db_keys[n_query_cols] =&str_status_col;
02009    db_vals[n_query_cols].type = DB_INT;
02010    db_vals[n_query_cols].nul = 0;
02011    db_vals[n_query_cols].val.int_val = subs->status;
02012    n_query_cols++;
02013                         
02014    db_keys[n_query_cols] = &str_inserted_time_col;
02015    db_vals[n_query_cols].type = DB_INT;
02016    db_vals[n_query_cols].nul = 0;
02017    db_vals[n_query_cols].val.int_val= (int)time(NULL);
02018    n_query_cols++;
02019    
02020    if(subs->reason.s && subs->reason.len)
02021    {
02022       db_keys[n_query_cols] =&str_reason_col;
02023       db_vals[n_query_cols].type = DB_STR;
02024       db_vals[n_query_cols].nul = 0;
02025       db_vals[n_query_cols].val.str_val = subs->reason;
02026       n_query_cols++;   
02027    }  
02028    
02029    if (pa_dbf.use_table(pa_db, &watchers_table) < 0) 
02030    {
02031       LM_ERR("in use_table\n");
02032       return -1;
02033    }
02034 
02035    if(pa_dbf.insert(pa_db, db_keys, db_vals, n_query_cols )< 0)
02036    {  
02037       LM_ERR("in sql insert\n");
02038       return -1;
02039    }
02040 
02041    return 0;
02042 }

Generated on Thu May 24 08:00:55 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6