resource_notify.c

Go to the documentation of this file.
00001 /*
00002  * $Id: resource_notify.c 2230 2007-06-06 07:13:20Z anca_vamanu $
00003  *
00004  * rls module - resource list server
00005  *
00006  * Copyright (C) 2007 Voice Sistem S.R.L.
00007  *
00008  * This file is part of Kamailio, a free SIP server.
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  *  2007-09-11  initial version (anca)
00027  */
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <libxml/parser.h>
00032 #include "../../parser/parse_content.h"
00033 #include "../../parser/parse_from.h"
00034 #include "../../cmpapi.h"
00035 #include "../pua/hash.h"
00036 #include "rls.h"
00037 #include "notify.h"
00038 #include "resource_notify.h"
00039 
00040 /* how to relate resource oriented dialogs to list_uri */
00041 /* sol1: use the same callid in Subscribe requests 
00042  * sol2: include an extra header
00043  * sol3: put the list_uri as the id of the record stored in
00044  * pua and write a function to return that id
00045  * winner: sol3
00046  * */
00047 static str su_200_rpl     = str_init("OK");
00048 
00049 #define CONT_COPY(buf, dest, source)\
00050    dest.s= (char*)buf+ size;\
00051    memcpy(dest.s, source.s, source.len);\
00052    dest.len= source.len;\
00053    size+= source.len;
00054 
00055 
00056 #define CONT_COPY_1 (buf, dest_s, dest_len, source_s, source_len)\
00057    dest_s= (char*)buf+ size;\
00058    memcpy(dest_s, source_s, source_len);\
00059    dest_len= source_len;\
00060    size+= source_len;
00061 
00062 int parse_subs_state(str auth_state, str** reason, int* expires)
00063 {
00064    str str_exp;
00065    str* res= NULL;
00066    char* smc= NULL;
00067    int len, flag= -1;
00068 
00069 
00070    if( strncmp(auth_state.s, "active", 6)== 0)
00071       flag= ACTIVE_STATE;
00072 
00073    if( strncmp(auth_state.s, "pending", 7)== 0)
00074       flag= PENDING_STATE; 
00075 
00076    if( strncmp(auth_state.s, "terminated", 10)== 0)
00077    {
00078       smc= strchr(auth_state.s, ';');
00079       if(smc== NULL)
00080       {
00081          LM_ERR("terminated state and no reason found");
00082          return -1;
00083       }
00084       if(strncmp(smc+1, "reason=", 7))
00085       {
00086          LM_ERR("terminated state and no reason found");
00087          return -1;
00088       }
00089       res= (str*)pkg_malloc(sizeof(str));
00090       if(res== NULL)
00091       {
00092          ERR_MEM(PKG_MEM_STR);
00093       }
00094       len=  auth_state.len- 10- 1- 7;
00095       res->s= (char*)pkg_malloc(len* sizeof(char));
00096       if(res->s== NULL)
00097       {
00098          ERR_MEM(PKG_MEM_STR);
00099       }
00100       memcpy(res->s, smc+ 8, len);
00101       res->len= len;
00102       return TERMINATED_STATE;
00103    }
00104 
00105    if(flag> 0)
00106    {
00107       smc= strchr(auth_state.s, ';');
00108       if(smc== NULL)
00109       {
00110          LM_ERR("active or pending state and no expires parameter found");
00111          return -1;
00112       }
00113       if(strncmp(smc+1, "expires=", 8))
00114       {
00115          LM_ERR("active or pending state and no expires parameter found");
00116          return -1;
00117       }
00118       str_exp.s= smc+ 9;
00119       str_exp.len= auth_state.s+ auth_state.len- smc- 9;
00120 
00121       if( str2int(&str_exp, (unsigned int*)expires)< 0)
00122       {
00123          LM_ERR("while getting int from str\n");
00124          return -1;
00125       }
00126       return flag;
00127    
00128    }
00129    return -1;
00130 
00131 error:
00132    if(res)
00133    {
00134       if(res->s)
00135          pkg_free(res->s);
00136       pkg_free(res);
00137    }
00138    return -1;
00139 }
00140 
00141 int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
00142 {
00143    struct to_body *pto, TO, *pfrom= NULL;
00144    str body= {0, 0};
00145    ua_pres_t dialog;
00146    str* res_id= NULL;
00147    db_key_t query_cols[9], result_cols[1];
00148    db_val_t query_vals[9];
00149    db_res_t* result= NULL;
00150    int n_query_cols= 0;
00151    str auth_state= {0, 0};
00152    int found= 0;
00153    str* reason= NULL;
00154    int auth_flag;
00155    struct hdr_field* hdr= NULL;
00156    int n, expires= -1;
00157    str content_type= {0, 0};
00158 
00159 
00160    LM_DBG("start\n");
00161    /* extract the dialog information and check if an existing dialog*/  
00162    if( parse_headers(msg,HDR_EOH_F, 0)==-1 )
00163    {
00164       LM_ERR("parsing headers\n");
00165       return -1;
00166    }
00167    if((!msg->event ) ||(msg->event->body.len<=0))
00168    {
00169       LM_ERR("Missing event header field value\n");
00170       return -1;
00171    }
00172    if( msg->to==NULL || msg->to->body.s==NULL)
00173    {
00174       LM_ERR("cannot parse TO header\n");
00175       return -1;
00176    }
00177    if(msg->to->parsed != NULL)
00178    {
00179       pto = (struct to_body*)msg->to->parsed;
00180       LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",
00181             pto->uri.len, pto->uri.s );   
00182    }
00183    else
00184    {
00185       memset( &TO , 0, sizeof(TO) );
00186       parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO);
00187       if(TO.uri.len <= 0) 
00188       {
00189          LM_ERR(" 'To' header NOT parsed\n");
00190          return -1;
00191       }
00192       pto = &TO;
00193    }
00194    dialog.watcher_uri= &pto->uri;
00195     if (pto->tag_value.s==NULL || pto->tag_value.len==0 )
00196    {  
00197       LM_ERR("to tag value not parsed\n");
00198       goto error;
00199    }
00200    dialog.from_tag= pto->tag_value;
00201    if( msg->callid==NULL || msg->callid->body.s==NULL)
00202    {
00203       LM_ERR("cannot parse callid header\n");
00204       goto error;
00205    }
00206    dialog.call_id = msg->callid->body;
00207 
00208    if (!msg->from || !msg->from->body.s)
00209    {
00210       LM_ERR("cannot find 'from' header!\n");
00211       goto error;
00212    }
00213    if (msg->from->parsed == NULL)
00214    {
00215       LM_DBG("'From' header not parsed\n");
00216       /* parsing from header */
00217       if ( parse_from_header( msg )<0 ) 
00218       {
00219          LM_ERR("cannot parse From header\n");
00220          goto error;
00221       }
00222    }
00223    pfrom = (struct to_body*)msg->from->parsed;
00224    dialog.pres_uri= &pfrom->uri;
00225       
00226    if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
00227    {
00228       LM_ERR("no from tag value present\n");
00229       goto error;
00230    }
00231    dialog.to_tag= pfrom->tag_value;
00232    dialog.flag|= RLS_SUBSCRIBE;
00233 
00234    dialog.event= get_event_flag(&msg->event->body);
00235    if(dialog.event< 0)
00236    {
00237       LM_ERR("unrecognized event package\n");
00238       goto error;
00239    }
00240    if(pua_get_record_id(&dialog, &res_id)< 0) // verify if within a stored dialog
00241    {
00242       LM_ERR("occured when trying to get record id\n");
00243       goto error;
00244    }
00245    if(res_id== 0)
00246    {
00247       LM_ERR("record not found\n");
00248       goto error;
00249    }
00250 
00251    /* extract the subscription state */
00252    hdr = msg->headers;
00253    while (hdr!= NULL)
00254    {
00255       if(cmp_hdrname_strzn(&hdr->name, "Subscription-State", 18)==0)  
00256       {
00257          found = 1;
00258          break;
00259       }
00260       hdr = hdr->next;
00261    }
00262    if(found==0 )
00263    {
00264       LM_ERR("'Subscription-State' header not found\n");
00265       goto error;
00266    }  
00267    auth_state = hdr->body;
00268 
00269    /* extract state and reason */
00270    auth_flag= parse_subs_state(auth_state, &reason, &expires);
00271    if(auth_flag< 0)
00272    {
00273       LM_ERR("while parsing 'Subscription-State' header\n");
00274       goto error;
00275    }
00276    if(msg->content_type== NULL || msg->content_type->body.s== NULL)
00277    {
00278       LM_DBG("cannot find content type header header\n");
00279    }
00280    else
00281       content_type= msg->content_type->body;
00282 
00283    /*constructing the xml body*/
00284    if(get_content_length(msg) == 0 )
00285    {
00286       goto done;
00287    }  
00288    else
00289    {
00290       if(content_type.s== 0)
00291       {
00292          LM_ERR("content length != 0 and no content type header found\n");
00293          goto error;
00294       }
00295       body.s=get_body(msg);
00296       if (body.s== NULL) 
00297       {
00298          LM_ERR("cannot extract body from msg\n");
00299          goto error;
00300       }
00301       body.len = get_content_length( msg );
00302 
00303    }
00304    /* update in rlpres_table where rlsusb_did= res_id and resource_uri= from_uri*/
00305    
00306    LM_DBG("body= %.*s\n", body.len, body.s);
00307 
00308    query_cols[n_query_cols]= &str_rlsubs_did_col;
00309    query_vals[n_query_cols].type = DB_STR;
00310    query_vals[n_query_cols].nul = 0;
00311    query_vals[n_query_cols].val.str_val= *res_id; 
00312    n_query_cols++;
00313    
00314    query_cols[n_query_cols]= &str_resource_uri_col;
00315    query_vals[n_query_cols].type = DB_STR;
00316    query_vals[n_query_cols].nul = 0;
00317    query_vals[n_query_cols].val.str_val= *dialog.pres_uri; 
00318    n_query_cols++;
00319 
00320    query_cols[n_query_cols]= &str_updated_col;
00321    query_vals[n_query_cols].type = DB_INT;
00322    query_vals[n_query_cols].nul = 0;
00323    query_vals[n_query_cols].val.int_val= UPDATED_TYPE; 
00324    n_query_cols++;
00325 
00326    query_cols[n_query_cols]= &str_auth_state_col;
00327    query_vals[n_query_cols].type = DB_INT;
00328    query_vals[n_query_cols].nul = 0;
00329    query_vals[n_query_cols].val.int_val= auth_flag; 
00330    n_query_cols++;
00331 
00332    if(reason)
00333    {
00334       query_cols[n_query_cols]= &str_reason_col;
00335       query_vals[n_query_cols].type = DB_STR;
00336       query_vals[n_query_cols].nul = 0;
00337       query_vals[n_query_cols].val.str_val= *reason;
00338       n_query_cols++;
00339    }
00340    query_cols[n_query_cols]= &str_content_type_col;
00341    query_vals[n_query_cols].type = DB_STR;
00342    query_vals[n_query_cols].nul = 0;
00343    query_vals[n_query_cols].val.str_val= content_type;
00344    n_query_cols++;
00345 
00346    query_cols[n_query_cols]= &str_presence_state_col;
00347    query_vals[n_query_cols].type = DB_STR;
00348    query_vals[n_query_cols].nul = 0;
00349    query_vals[n_query_cols].val.str_val= body;
00350    n_query_cols++;
00351    
00352    query_cols[n_query_cols]= &str_expires_col;
00353    query_vals[n_query_cols].type = DB_INT;
00354    query_vals[n_query_cols].nul = 0;
00355    query_vals[n_query_cols].val.int_val= expires+ (int)time(NULL);
00356    n_query_cols++;
00357 
00358    if (rls_dbf.use_table(rls_db, &rlpres_table) < 0) 
00359    {
00360       LM_ERR("in use_table\n");
00361       goto error;
00362    }
00363    /* query-> if not present insert // else update */
00364    result_cols[0]= &str_updated_col;
00365 
00366    if(rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols,
00367                2, 1, 0, &result)< 0)
00368    {
00369       LM_ERR("in sql query\n");
00370       if(result)
00371          rls_dbf.free_result(rls_db, result);
00372       goto error;
00373    }
00374    if(result== NULL)
00375       goto error;
00376    n= result->n;
00377    rls_dbf.free_result(rls_db, result);
00378 
00379    if(n<= 0)
00380    {
00381       if(rls_dbf.insert(rls_db, query_cols, query_vals, n_query_cols)< 0)
00382       {
00383          LM_ERR("in sql insert\n");
00384          goto error;
00385       }
00386       LM_DBG("Inserted in database table new record\n");
00387    }
00388    else
00389    {
00390       LM_DBG("Updated in db table already existing record\n");
00391       if(rls_dbf.update(rls_db, query_cols, 0, query_vals, query_cols+2,
00392                   query_vals+2, 2, n_query_cols-2)< 0)
00393       {
00394          LM_ERR("in sql update\n");
00395          goto error;
00396       }
00397    }
00398    
00399    LM_DBG("Updated rlpres_table\n");   
00400    /* reply 200OK */
00401 done:
00402    if( slb.send_reply(msg, 200, &su_200_rpl)== -1)
00403    {
00404       LM_ERR("while sending reply\n");
00405       goto error;
00406    }  
00407 
00408    return 1;
00409 
00410 error:
00411    return -1;
00412 }
00413 /* callid, from_tag, to_tag parameters must be allocated */
00414 
00415 int parse_rlsubs_did(char* str_did, str* callid, str* from_tag, str* to_tag)
00416 {
00417    char* smc= NULL;
00418 
00419    smc= strstr(str_did, DID_SEP);
00420    if(smc== NULL)
00421    {
00422       LM_ERR("bad format for resource list Subscribe dialog"
00423             " indentifier[rlsubs did]= %s\n", str_did);
00424       return -1;
00425    }
00426    callid->s= str_did;
00427    callid->len= smc- str_did;
00428          
00429    from_tag->s= smc+ DID_SEP_LEN;
00430    smc= strstr(from_tag->s, DID_SEP);
00431    if(smc== NULL)
00432    {
00433       LM_ERR("bad format for resource list Subscribe dialog"
00434             " indentifier(rlsubs did)= %s\n", str_did);
00435       return -1;
00436    }
00437    from_tag->len= smc- from_tag->s;
00438       
00439    to_tag->s= smc+ DID_SEP_LEN;
00440    to_tag->len= strlen(str_did)- 2* DID_SEP_LEN- callid->len- from_tag->len;
00441 
00442    return 0;
00443 }
00444 
00445 void timer_send_notify(unsigned int ticks,void *param)
00446 {
00447    db_key_t query_cols[2], update_cols[1], result_cols[7];
00448    db_val_t query_vals[2], update_vals[1];
00449    int did_col, resource_uri_col, auth_state_col, reason_col,
00450       pres_state_col, content_type_col;
00451    int n_result_cols= 0, i;
00452    db_res_t *result= NULL;
00453    char* prev_did= NULL, * curr_did= NULL;
00454    db_row_t *row; 
00455    db_val_t *row_vals;
00456    char* resource_uri, *pres_state;
00457    str callid, to_tag, from_tag;
00458    xmlDocPtr rlmi_doc= NULL;
00459    xmlNodePtr list_node= NULL, instance_node= NULL, resource_node;
00460    unsigned int hash_code= 0;
00461    int len;
00462    int size= BUF_REALLOC_SIZE, buf_len= 0;   
00463    char* buf= NULL, *auth_state= NULL, *boundary_string= NULL, *cid= NULL;
00464    int contor= 0, auth_state_flag, antet_len;
00465    str bstr= {0, 0};
00466    str rlmi_cont= {0, 0}, multi_cont;
00467    subs_t* s, *dialog= NULL;
00468    char* rl_uri= NULL;
00469 
00470    query_cols[0]= &str_updated_col;
00471    query_vals[0].type = DB_INT;
00472    query_vals[0].nul = 0;
00473    query_vals[0].val.int_val= UPDATED_TYPE; 
00474 
00475    result_cols[did_col= n_result_cols++]= &str_rlsubs_did_col;
00476    result_cols[resource_uri_col= n_result_cols++]= &str_resource_uri_col;
00477    result_cols[auth_state_col= n_result_cols++]= &str_auth_state_col;
00478    result_cols[content_type_col= n_result_cols++]= &str_content_type_col;
00479    result_cols[reason_col= n_result_cols++]= &str_reason_col;
00480    result_cols[pres_state_col= n_result_cols++]= &str_presence_state_col;
00481 
00482    /* query in alfabetical order after rlsusbs_did 
00483     * (resource list Subscribe dialog indentifier)*/
00484 
00485    if (rls_dbf.use_table(rls_db, &rlpres_table) < 0) 
00486    {
00487       LM_ERR("in use_table\n");
00488       goto done;
00489    }
00490 
00491    if(rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols,
00492                1, n_result_cols, &str_rlsubs_did_col, &result)< 0)
00493    {
00494       LM_ERR("in sql query\n");
00495       goto done;
00496    }
00497    if(result== NULL || result->n<= 0)
00498       goto done;
00499 
00500    /* update the rlpres table */
00501    update_cols[0]= &str_updated_col;
00502    update_vals[0].type = DB_INT;
00503    update_vals[0].nul = 0;
00504    update_vals[0].val.int_val= NO_UPDATE_TYPE; 
00505 
00506    if (rls_dbf.use_table(rls_db, &rlpres_table) < 0) 
00507    {
00508       LM_ERR("in use_table\n");
00509       goto error;
00510    }
00511    if(rls_dbf.update(rls_db, query_cols, 0, query_vals, update_cols,
00512                update_vals, 1, 1)< 0)
00513    {
00514       LM_ERR("in sql update\n");
00515       goto error;
00516    }
00517 
00518    /* generate the boundary string */
00519 
00520    boundary_string= generate_string((int)time(NULL), BOUNDARY_STRING_LEN);
00521    bstr.len= strlen(boundary_string);
00522    bstr.s= (char*)pkg_malloc((bstr.len+ 1)* sizeof(char));
00523    if(bstr.s== NULL)
00524    {
00525       ERR_MEM(PKG_MEM_STR);
00526    }
00527    memcpy(bstr.s, boundary_string, bstr.len);
00528    bstr.s[bstr.len]= '\0';
00529 
00530    /* for the multipart body , use here also an initial allocated
00531     * and reallocated on need buffer */
00532    buf= pkg_malloc(size* sizeof(char));
00533    if(buf== NULL)
00534    {
00535       ERR_MEM(PKG_MEM_STR);
00536    }
00537 
00538    antet_len= COMPUTE_ANTET_LEN(bstr.s);
00539    LM_DBG("found %d records with updated state\n", result->n);
00540    for(i= 0; i< result->n; i++)
00541    {
00542       row = &result->rows[i];
00543       row_vals = ROW_VALUES(row);
00544       
00545       curr_did=     (char*)row_vals[did_col].val.string_val;
00546       resource_uri= (char*)row_vals[resource_uri_col].val.string_val;
00547       auth_state_flag=     row_vals[auth_state_col].val.int_val;
00548       pres_state=   (char*)row_vals[pres_state_col].val.string_val;
00549       
00550       if(prev_did!= NULL && strcmp(prev_did, curr_did)) 
00551       {
00552          xmlDocDumpFormatMemory(rlmi_doc,(xmlChar**)(void*)&rlmi_cont.s,
00553             &rlmi_cont.len, 1);
00554       
00555          multi_cont.s= buf;
00556          multi_cont.len= buf_len;
00557 
00558           if(agg_body_sendn_update(&dialog->pres_uri, bstr.s, &rlmi_cont, 
00559                    (buf_len==0)?NULL:&multi_cont, dialog, hash_code)<0)
00560           {
00561              LM_ERR("in function agg_body_sendn_update\n");
00562              goto error;
00563           }
00564          xmlFree(rlmi_cont.s);
00565          if(buf_len)    
00566          {  
00567             pkg_free(buf);
00568             buf= NULL;
00569          }
00570          xmlFreeDoc(rlmi_doc);
00571          rlmi_doc= NULL;
00572          pkg_free(rl_uri);
00573          rl_uri= NULL;
00574          pkg_free(dialog);
00575          dialog= NULL;
00576       }
00577 
00578       if(prev_did== NULL || strcmp(prev_did, curr_did)) /*if first or different*/
00579       {
00580          /* search the subscription in rlsubs_table*/    
00581          if( parse_rlsubs_did(curr_did, &callid, &from_tag, &to_tag)< 0)
00582          {
00583             LM_ERR("bad format for "
00584                "resource list Subscribe dialog indentifier(rlsubs did)\n");
00585             goto done;
00586 
00587          }
00588          hash_code= core_hash(&callid, &to_tag, hash_size);
00589       
00590          lock_get(&rls_table[hash_code].lock);
00591          s= pres_search_shtable(rls_table,callid,to_tag,from_tag,hash_code);
00592          if(s== NULL)
00593          {
00594             LM_DBG("record not found in hash_table [rlsubs_did]= %s\n",
00595                   curr_did);
00596             LM_DBG("callid= %.*s\tfrom_tag= %.*s\tto_tag= %.*s\n",
00597                   callid.len, callid.s,from_tag.len,from_tag.s,
00598                   to_tag.len,to_tag.s);
00599             lock_release(&rls_table[hash_code].lock);
00600             continue;
00601          }
00602          LM_DBG("Found rl-subs record in hash table\n");
00603                
00604          /* save dialog info and rl_uri*/
00605          dialog= pres_copy_subs(s, PKG_MEM_TYPE);
00606          if(dialog== NULL)
00607          {  
00608             LM_ERR("while copying subs_t structure\n");
00609             lock_release(&rls_table[hash_code].lock);
00610             goto done;
00611          }  
00612          lock_release(&rls_table[hash_code].lock);
00613 
00614          /* make new rlmi and multipart documents */
00615          rlmi_doc= xmlNewDoc(BAD_CAST "1.0");
00616          if(rlmi_doc== NULL)
00617          {
00618             LM_ERR("when creating new xml doc\n");
00619             goto done;
00620          }
00621          list_node= xmlNewNode(NULL, BAD_CAST "list");
00622          if(list_node== NULL)
00623          {
00624             LM_ERR("while creating new xml node\n");
00625             goto done;
00626          }
00627          rl_uri= (char*)pkg_malloc((dialog->pres_uri.len+ 1)* sizeof(char));
00628          if(rl_uri==  NULL)
00629          {
00630             ERR_MEM(PKG_MEM_STR);
00631          }
00632          memcpy(rl_uri, dialog->pres_uri.s, dialog->pres_uri.len);
00633          rl_uri[dialog->pres_uri.len]= '\0';
00634 
00635          xmlNewProp(list_node, BAD_CAST "uri", BAD_CAST rl_uri);
00636          xmlNewProp(list_node, BAD_CAST "xmlns", BAD_CAST "urn:ietf:params:xml:ns:rlmi");
00637          xmlNewProp(list_node, BAD_CAST "version", BAD_CAST int2str(dialog->version, &len));
00638          xmlNewProp(list_node, BAD_CAST "fullState", BAD_CAST "false");
00639 
00640          xmlDocSetRootElement(rlmi_doc, list_node);
00641          buf_len= 0;
00642 
00643          /* !!!! for now I will include the auth state without checking if 
00644           * it has changed - > in future chech if it works */     
00645       }     
00646 
00647       /* add a node in rlmi_doc and if any presence state registered add 
00648        * it in the buffer */
00649       
00650       resource_node= xmlNewChild(list_node,NULL,BAD_CAST "resource", NULL);
00651       if(resource_node== NULL)
00652       {
00653          LM_ERR("when adding resource child\n");
00654          goto done;
00655       }
00656       xmlNewProp(resource_node, BAD_CAST "uri", BAD_CAST resource_uri);
00657          
00658       /* there might be more records with the same uri- more instances-
00659        * search and add them all */
00660       
00661       contor= 0;
00662       while(1)
00663       {
00664          contor++;
00665          cid= NULL;
00666          instance_node= xmlNewChild(resource_node, NULL, 
00667                BAD_CAST "instance", NULL);
00668          if(instance_node== NULL)
00669          {
00670             LM_ERR("while adding instance child\n");
00671             goto error;
00672          }
00673          xmlNewProp(instance_node, BAD_CAST "id", 
00674                BAD_CAST generate_string(contor, 8));
00675          
00676          auth_state= get_auth_string(auth_state_flag);
00677          if(auth_state== NULL)
00678          {
00679             LM_ERR("bad authorization status flag\n");
00680             goto error;
00681          }
00682          xmlNewProp(instance_node, BAD_CAST "state", BAD_CAST auth_state);
00683       
00684          if(auth_state_flag & ACTIVE_STATE)
00685          {
00686             cid= generate_cid(resource_uri, strlen(resource_uri));
00687             xmlNewProp(instance_node, BAD_CAST "cid", BAD_CAST cid);
00688          }
00689          else
00690          if(auth_state_flag & TERMINATED_STATE)
00691          {
00692             xmlNewProp(instance_node, BAD_CAST "reason",
00693                BAD_CAST row_vals[resource_uri_col].val.string_val);
00694          }
00695       
00696          /* add in the multipart buffer */
00697          if(cid)
00698          {
00699             if(buf_len+ antet_len+ strlen(pres_state)+ 4 > size)
00700             {
00701                REALLOC_BUF
00702             }
00703             buf_len+= sprintf(buf+ buf_len, "--%s\r\n\r\n", bstr.s);
00704             buf_len+= sprintf(buf+ buf_len, "Content-Transfer-Encoding: binary\r\n");
00705             buf_len+= sprintf(buf+ buf_len, "Content-ID: <%s>\r\n", cid);
00706             buf_len+= sprintf(buf+ buf_len, "Content-Type: %s\r\n\r\n",  
00707                   row_vals[content_type_col].val.string_val);
00708             buf_len+= sprintf(buf+buf_len,"%s\r\n\r\n", pres_state);
00709          }
00710 
00711          i++;
00712          if(i== result->n)
00713          {
00714             i--;
00715             break;
00716          }
00717 
00718          row = &result->rows[i];
00719          row_vals = ROW_VALUES(row);
00720       
00721          if(strncmp(resource_uri, row_vals[resource_uri_col].val.string_val,
00722                strlen(resource_uri))
00723             || strncmp(curr_did, row_vals[did_col].val.string_val,
00724                strlen(curr_did)))
00725          {
00726             i--;
00727             break;
00728          }
00729          resource_uri= (char*)row_vals[resource_uri_col].val.string_val;
00730          auth_state_flag=     row_vals[auth_state_col].val.int_val;
00731          pres_state=   (char*)row_vals[pres_state_col].val.string_val;
00732       }
00733 
00734       prev_did= curr_did;
00735    }
00736 
00737    if(rlmi_doc)
00738    {
00739       xmlDocDumpFormatMemory( rlmi_doc,(xmlChar**)(void*)&rlmi_cont.s,
00740       &rlmi_cont.len, 1);
00741       
00742       multi_cont.s= buf;
00743       multi_cont.len= buf_len;
00744    
00745        if(agg_body_sendn_update(&dialog->pres_uri, bstr.s, &rlmi_cont, 
00746           (buf_len==0)?NULL:&multi_cont, dialog, hash_code)<0)
00747        {
00748           LM_ERR("in function agg_body_sendn_update\n");
00749           goto error;
00750       }
00751       xmlFree(rlmi_cont.s);
00752       if(buf_len)    
00753       {  
00754          pkg_free(buf);
00755          buf= NULL;
00756       }
00757       pkg_free(rl_uri);
00758       rl_uri= NULL;
00759       pkg_free(dialog);
00760       dialog= NULL;
00761    }
00762 
00763 
00764 error:
00765 done:
00766    if(result)
00767       rls_dbf.free_result(rls_db, result);
00768    if(rlmi_doc)
00769       xmlFreeDoc(rlmi_doc);
00770    if(rl_uri)
00771       pkg_free(rl_uri);
00772    if(bstr.s)
00773       pkg_free(bstr.s);
00774       
00775    if(buf)
00776       pkg_free(buf);
00777    if(dialog)
00778       pkg_free(dialog);
00779    return;
00780 }
00781 
00782 
00783 /* function to periodicaly clean the rls_presentity table */
00784 
00785 void rls_presentity_clean(unsigned int ticks,void *param)
00786 {
00787    db_key_t query_cols[2];
00788    db_op_t query_ops[2];
00789    db_val_t query_vals[2];
00790 
00791    query_cols[0]= &str_expires_col;
00792    query_ops[0]= OP_LT;
00793    query_vals[0].nul= 0;
00794    query_vals[0].type= DB_INT;
00795    query_vals[0].val.int_val= (int)time(NULL) - 10;
00796 
00797    if (rls_dbf.use_table(rls_db, &rlpres_table) < 0) 
00798    {
00799       LM_ERR("in use_table\n");
00800       return ;
00801    }
00802 
00803    if(rls_dbf.delete(rls_db, query_cols, query_ops, query_vals, 1)< 0)
00804    {
00805       LM_ERR("in sql delete\n");
00806       return ;
00807    }
00808 
00809 }

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